Java中的线程同步有几种方式,synchronized关键字和wait(),notify()下面就来对这两种方式展开描述一下:
synchronized关键字可以用于方法和代码块,若用于方法,默认是对当前实例加锁。而用于代码块时可以指定加锁对象(或者Class),这种加锁方式非常简单,而且一般情况下效率也不差。但是要
sychronized和wait()/notify方法的关系是什么呢?简而言之:synchronized可以单独存在,而wait()/notify()必须在synchronized代码块中间。wait()/notify()/notifyAll()
调用object.wait()方法后该线程进入对象的wait set,放弃线程被调度执行的机会,直到如下情形发生:
1.其它线程调用notify/notifyAll方法。当调用notify使一个线程获得竞争CPU调度的机会,其它线程继续在wait set中继续等待;调用notifyAll()时所有线程逐渐离开wait set,但是同一时间只能有一个线程拥有monitor,所以此时该线程也是竞争CPU调度,线程状态为BLOCKED。
2.其它线程中断该线程thread.interrupt(),被中断线程的wait方法将会抛出中断异常,但并不会立刻抛出异常,会开始竞争CPU调度,如果获得执行则获得当前对象的锁并抛出异常
3.若在wait(long timeout)参数中设置了超时时间,则当超时时间到达(进入BLOCKED状态)也会竞争该同步锁,先获得同步锁的线程会先被执行。
lock的几个区域
若线程在请求而且从未获得过锁就进入entryset,当线程获得锁后又执行了object.wait()就进入waitset
WAITING (on object monitor)说明线程已经进入synchronized块
waiting for monitor entry [0x00007fd4f8684000]:正在等待进入entryset,其中0x00007fd4f8684000为线程栈起始地址
in Object.wait():正在等待进入waitset
Waiting on condition:等待资源()
线程有如下几个状态:
NEW:线程被创建但是还没有被执行
RUNNABLE:线程正在占用cpu并且在执行任务
BLOCKED:线程为了获得监视器需要等待其他线程释放锁
WAITING:调用了wait,join,park方法使线程等待-无限期等待
TIMED_WAITING:调用了sleep,wait,join,park方法使线程等待--有限期等待
线程的状态装换图:
Blocked:
1.对于进入了同步块并且wait已经到达了指定等待时间的线程将会进入BLOCKED状态,线程信息如下:
"wait-thread3" prio=6 tid=0x0000000008ef8800 nid=0x87d8 waiting for monitor entry [0x00000000097ef000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.csii.parent.WaitRunner.run(WaitRunner.java:12)
- waiting to lock <0x00000000ff62c528> (a java.lang.Object)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- None
线程由始至终都没有获得过锁
2.对于等待进入同步块的进程也处于BLOCKED状态
"wait-thread2" prio=6 tid=0x0000000008116800 nid=0x712c waiting for monitor entry [0x0000000008def000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000ff62c528> (a java.lang.Object)
at com.csii.parent.WaitRunner.run(WaitRunner.java:15)
- locked <0x00000000ff62c528> (a java.lang.Object)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- None
"wait-thread1" prio=6 tid=0x0000000008115800 nid=0x7e84 waiting for monitor entry [0x0000000008cef000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000ff62c528> (a java.lang.Object)
at com.csii.parent.WaitRunner.run(WaitRunner.java:15)
- locked <0x00000000ff62c528> (a java.lang.Object)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- None
可以看到线程先是得到了锁,后来又释放了锁