深入研究 Java Synchronize 和 Lock 的得地的区别及用法与用法

最近看公司以前的代码,现在给出大致的结构

}为什么里面还要在有一个synchronize(threadLock),如果一个线程执行deal方法,就要获得demo实例的对象锁,才会执行,

执行那个代码块需要获得threadLock的对象锁,个人认为没有必要在加这个锁吧。本来外面方法就是同步的。

哪位懂的话解释一下,谢谢。

有必要,就是在synchronized this的前提下还有同步竞争,比如说同一个对象里头还有东西要做竞争。

同步竞争 后还是只是一个线程进入方法内啊,能举个例子说一下吗

谢谢,我明白了,刚才看了一下的确是别的方法里还有同样的操作,所以就加了这样一个锁。我只注意了外面的嵌套。

匿名用户不能发表回复!

版权声明:本文为博主原创文章,未经博主允许不得转载。 /u/article/details/

        Synchronize对一般方法的修饰和对代码块的修饰没有什么区别,对代码块的修饰作用范围是Synchronize(this){ // 作用范围},大括号中的代码是作用范围,而对方法修饰的作用范围就是整个方法。如果把代码块中的代码提出来作为一个方法二者没有什么本质上的区别。

        除了对一般方法修饰Synchronize还可以对静态方法进行修饰,我们知道类中的静态方法是属于所有实例化的对象的,可以推断如果Synchronize修饰一个静态方法那么该类所有实例化出来的对象对这个方法都是线程同步的。通过如下的实例验证:

       本次虽然也是实例化的两个线程类,但是运行的结果却和只有一个线程实例类是一样的,因为在run中调用的是test这个静态的方法,这个方法时属于所有的对象,所以即使实例化的三个线程类,它们还是保持同步的。

JDK1.5中,synchronized是性能低效的。因为这是一个重量级操作,它对性能最大的影响是阻塞的是实现,挂起线程和恢复线程的操作都需要转入内核态中完成,这些操作给系统的并发性带来了很大的压力。相比之下使用Java提供的Lock对象,性能更高一些。多线程环境下,synchronized的吞吐量下降的非常严重,而ReentrankLock则能基本保持在同一个比较稳定的水平上。

到了JDK1.6,发生了变化,对synchronize加入了很多优化措施,有自适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在JDK1.6上synchronize的性能并不比Lock差。官方也表示,他们也更支持synchronize,在未来的版本中还有优化余地,所以还是提倡在synchronized能实现需求的情况下,优先考虑使用synchronized来进行同步。

下面浅析以下两种锁机制的底层的实现策略。

1.互斥同步最主要的问题就是进行线程阻塞和唤醒所带来的性能问题,因而这种同步又称为阻塞同步,它属于一种悲观的并发策略,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。synchronized采用的便是这种并发策略。
2.随着指令集的发展,我们有了另一种选择:基于冲突检测的乐观并发策略,通俗地讲就是先进性操作,如果没有其他线程争用共享数据,那操作就成功了,如果共享数据被争用,产生了冲突,那就再进行其他的补偿措施(最常见的补偿措施就是不断地重拾,直到试成功为止),这种乐观的并发策略的许多实现都不需要把线程挂起,因此这种同步被称为非阻塞同步。ReetrantLock采用的便是这种并发策略。
3.在乐观的并发策略中,需要操作和冲突检测这两个步骤具备原子性,它靠硬件指令来保证,这里用的是CAS操作(Compare and Swap)。JDK1.5之后,Java程序才可以使用CAS操作。我们可以进一步研究ReentrantLock的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState,这里其实就是调用的CPU提供的特殊指令。现代的CPU提供了指令,可以自动更新共享数据,而且能够检测到其他线程的干扰,而compareAndSet() 就用这些代替了锁定。这个算法称作非阻塞算法,意思是一个线程的失败或者挂起不应该影响其他线程的失败或挂起。

基本语法上,ReentrantLock与synchronized很相似,它们都具备一样的线程重入特性,只是代码写法上有点区别而已,一个表现为API层面的互斥锁(Lock),一个表现为原生语法层面的互斥锁(synchronized)。ReentrantLock相对synchronized而言还是增加了一些高级功能,主要有以下三项:

1、等待可中断:当持有锁的线程长期不释放锁时,正在等待的线程可以选择放弃等待,改为处理其他事情,它对处理执行时间非常上的同步块很有帮助。而在等待由synchronized产生的互斥锁时,会一直阻塞,是不能被中断的。
2、可实现公平锁:多个线程在等待同一个锁时,必须按照申请锁的时间顺序排队等待,而非公平锁则不保证这点,在锁释放时,任何一个等待锁的线程都有机会获得锁。synchronized中的锁时非公平锁,ReentrantLock默认情况下也是非公平锁,但可以通过构造方法ReentrantLock(ture)来要求使用公平锁。
3、锁可以绑定多个条件:ReentrantLock对象可以同时绑定多个Condition对象(名曰:条件变量或条件队列),而在synchronized中,锁对象的wait()和notify()或notifyAll()方法可以实现一个隐含条件,但如果要和多于一个的条件关联的时候,就不得不额外地添加一个锁,而ReentrantLock则无需这么做,只需要多次调用newCondition()方法即可。而且我们还可以通过绑定Condition对象来判断当前线程通知的是哪些线程(即与Condition对象绑定在一起的其他线程)。

我要回帖

更多关于 的得地的区别及用法 的文章

 

随机推荐