多线程基础之同步代码块

来源:互联网 发布:自己实现java虚拟机 编辑:程序博客网 时间:2024/06/08 18:21
           

    同步方法在同一时刻只能锁定一个对象(即同步方法所属的对象),在并发执行中有时需要锁定的对象不止一个。另外,同步方法会形象执行效率,因此,应该尽量减少同步范围,提高程序的并发性。而同步代码块可以解决上述问题。

synchronized (<资源对象引用>){    //需要同步的代码}
(1)资源对象引用指向的是要被锁定的资源对象,同步代码块中的代码是对资源进行的操作,这些代码在同一时刻不允许多个线程执行。

(2)线程必须先获得资源对象引用所指向的对象的锁(注意:所用的锁,因为可以存在有多个引用),才能执行同步代码块中的代码。

(3)同步代码块中的线程一样可以调用资源对象的wait方法,释放锁,进入等待池等待,一样可以使用notify()/notifyAll()去唤醒等待池中的等待线程。

(4)同步代码块执行结束,锁释放。

注意:java中资源对象的线程等待池不止一种,例如有调用wait方法后进入的wait资源等待池,也有等待获得锁的锁等待池,锁等待池中的线程在锁被释放后会自动尝试再次获取锁,而wait资源等待池中的 线程只有在wait时间到或收到notifyAll的通知才唤醒执行。当然有可能线程在wait资源等待池中被唤醒后由于没有获得锁,进入了锁等待池。

package test11;public class MyThread extends Thread{//该引用为资源对象private Object resource;public MyThread(){}public MyThread(String name,Object resource){this.setName(name);this.resource = resource;}@Overridepublic void run() {//同步语句块synchronized (resource) {System.out.println(this.getName()+"线程获得了锁,访问了资源!");System.out.println(this.getName()+"线程带着锁去休息了。。。");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(this.getName()+"线程醒了代码执行完,锁释放了!");}}}

package test11;public class Main {public static void main(String[] args) {//创建资源对象Object  resource = new Object();//创建线程,并将资源对象传给每一个线程Thread t1 = new MyThread("t1",resource);Thread t2 = new MyThread("t2",resource);t1.start();t2.start();}}

运行结果:

t1线程获得了锁,访问了资源!t1线程带着锁去休息了。。。t1线程醒了代码执行完,锁释放了!t2线程获得了锁,访问了资源!t2线程带着锁去休息了。。。t2线程醒了代码执行完,锁释放了!

注意:(1)sleep方法并不会释放锁
           (2)调用的wait(),notify(),notifyAll()方法都属于被锁定的资源对象,锁定的是谁,只能调用谁的这些方法

线程的死锁:java中死锁的含义是:线程之间互相等待对方释放资源对象的锁,而每个线程有持有其他线程需要的锁,造成几个线程出处在永久的相互等待之中。

0 0
原创粉丝点击