synchronized 同步语句块
synchronized关键字声明在方法上某些情况下是有弊端的,比如线程A调用同步方法执行了一个长时间的任务,那么B线程必须要等待较长时间,这种情况下必须使用synchronized同步语块句来解决。
1.1synchronized方法的弊端
输出结果:在使用synchronized关键字声明方法,从运行时间来看,弊端很明显,解决这样的问题使用synchronized同步块
1.2 synchronized同步代码块的使用:
当两个并发线程访问同一个对象object中synchronized(this)同步代码块时,一段时间内只有一个线程被执行,另外一个线程必须等待当前线程执行完这个代码才能执行该代码块。
输出结果:虽然使用synchronized同步代码块,但是执行的效率还是没有提高,执行的效果还是同步运行的。
那么问题来了,如何使用synchronized同步代码块解决程序执行效率低的问题?
稍作修改,如下:
通过上面的示例,当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以访问该object对象中的非synchronized(this)同步代码块。
1.3 一半异步,一半同步
不在synchronized中就是异步执行,在synchronized块中就是同步执行。
输出结果:非同步部分,线程交叉执行
同步代码块中的,同步执行。
1.4 synchronized代码块间的同步性
输出结果:A线程执行完释放锁,B线程才执行。两个同步代码块按顺序执行。
验证synchronized(this)代码块是锁定当前对象的
输出结果:没有引用synchronized的方法,正常被线程调用.,不用等待另外线程释放锁。
如果将没有引用synchronized的方法加上synchronized关键字,那么效果就不一样了。
我们也可以将任意对象作为对象监视器
比如:
这还是同步的效果:如果换一种写法,就是异步执行的。
如果线程拥有的对象监视器不同,运行结果就是异步的。
但是同步代码块放在非同步synchronized方法中进行声明,并不能保证调用方法的线程的执行同步/顺序性,也就是线程调用方法的顺序是无序的,虽然在同步代码块执行的顺序是同步的,这样会出现脏读的现象。
使用synchronized(非this对象)同步代码块,可以解决脏读,但是再解决脏读之前,做个实验,证明多个线程调用同一个方法是随机的。
当前线程的执行和离开是同步执行的,成对出现的,但是线程之间的执行确实异步的。所以就会出现脏读的环境,当两个线程执行带有分支判断的方法时,就会出现逻辑上的错误。,出现脏读,演示下脏读的案例。
锁对象的改变
输出结果:结果是异步的。