java多线程(2) —sychronized

越努力越幸运!

 sychronized篇

一. sychronized的介绍

在Java中内置了语言级的同步原语--synchronized

synchronized是通过互斥达到同步的。

二. sychronized的应用

synchronized关键字的作用域有二种: 
1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法; 
2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;

3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;

Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

     一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

     二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

     三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

     四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

     五、以上规则对其它对象锁同样适用.

三. sychronized的底层实现

Synchronized的底层实现是依靠moniter锁的,每一个对象都会带有一个moniter锁。与Synchronized实现相关的指令有monitorenter和monitorexit。

每执行一次monitorenter指令的时候,计数器的值就会+1,每执行一次monitorexit指令的时候,计数器的值就会-1,当计数器不为0的时候,还是可以执行monitorenter指令的,这就是可重入性,

每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:

如果monitor的计数器为0,则该线程进入monitor,然后将计数器数设置为1,该线程即为monitor的所有者。

如果线程已经占有该monitor,只是重新进入,则进入monitor的计数器数加1。

如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。

 执行monitorexit的线程必须是objectref所对应的monitor的所有者。

指令执行时,monitor的计数器数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。

其他被这个monitor阻塞的线程可以尝试去获取这个monitor 的所有权。

四. sychronized的常见面试题

1.面试官:sychronized lock的区别?

答:1.sychronized是非公平锁  lock可以是公平锁和非公平锁

       2.lock是一个接口,而synchronized是java的一个关键字,synchronized是内置的语言实现;

      3.synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而lock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。(所以最好将同步代码块用try catch包起来,finally中写入unlock,避免死锁的发生。) 

      4.lock等待锁过程中可以用interrupt来终端等待,而synchronized只能等待锁的释放,不能响应中断;

      5.4. lock可以通过trylock来知道有没有获取锁,而synchronized不能;

猜你喜欢

转载自blog.csdn.net/hezuo1181/article/details/82944632