Java 同步 synchronized与lock

实现线程同步一个使synchronized关键字,一个是通过对象lock.
Lock 在jdk 1.5才出现的,在一定程度上缓解了synchronized同步所带来的性能下降。

Synchronized

synchronized时对象一定会被阻塞,其他线程必须等待锁释放后才能执行,在高并发的情况下,很容易降低性能,而且不容易控制会出现死锁。
原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。

Lock

需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类做为对象才能保证锁的生效。且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。
lockk用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap).

public class LockTest {  
    public static void main(String[] args) {  
        final Outputter1 output = new Outputter1();  
        new Thread() {  
            public void run() {  
                output.output("zhangsan");  
            };  
        }.start();        
        new Thread() {  
            public void run() {  
                output.output("lisi");  
            };  
        }.start();  
    }  
}  
class Outputter1 {  
    private Lock lock = new ReentrantLock();// 锁对象  
    public void output(String name) {  
        // TODO 线程输出方法  
        lock.lock();// 得到锁  
        try {  
            for(int i = 0; i < name.length(); i++) {  
                System.out.print(name.charAt(i));  
            }  
        } finally {  
            lock.unlock();// 释放锁  
        }  
    }  
}  

Synchronized 和Lock

synchronized 要比lock同步的性能消耗高,而lock比synchronized优越就优越在的java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,这样就可以基于lock实现不同的调用算法、性能特性或者锁定语义。
我们之前说synchronized在多线程竞争激烈的时候可能会出现性能极速下降的问题。ReentrantLock在多线程抢占资源的时候可以保障当许多线程都想访问共享资源时,JVM 可以花更少的时候来调度线程,把更多时间用在执行线程上。
利用ReentrantLock()来保护共享资源。

Lock lock = new ReentrantLock();  
lock.lock();  
try {   
  // update object state  
}  
finally {  
  lock.unlock();   
}  

ReentrantLock获得锁的方式

lock(),如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,知道获取锁
trylock(),如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false
trylock(),如果获取了锁立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待过程如果获得了锁,则返回true,如果等待超时,则返回false。
lockInterruptibly,如果截取了锁则立即返回,如果没有获取锁定,当前线程处于休眠状态,直到获得锁,或者是当前线程被别的线程中断。
我们看出使用ReentrantLock来实现同步相对于Synchronized更灵活,
一方面
在Synchronized中使用同步可能会出现等待持有对象锁的线程释放锁,但是如果这个线程的周期很长,在这个过程中等待中的线程可能会一直等待直到等死。这样就消耗了大量了系统资源。
另一方面出现死锁的可能性更大,线程A拿到锁,并且runing,而线程B等待A释放锁,如果A需要B中的资源,就陷入了无限等待的过程中了。
最后,在多线程共享资源时,减少了线程间切换所花费得资源,对CPU的利用率比较低。
ReentrantLock给了一种机制让我们来响应中断,可能自行中断,也可以被线性中断,是很灵活的。
应用场景:
lock支持的时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者锁投票。
synchronized可以实现的功能,基本上lock都能实现。虽然看起来lock的出现似乎已经可以取代synchronized,但是synchronized似乎也有些优点,lock中的锁定类是用于高级用户和高级情况的工具,如果在没有特别的需求的情况下一般还是以使用synchronized为主,另外,lock需要程序员手动加锁和手动释放锁,而synchronized在退出 synchronized 块时JVM就能自动的释放锁。

参考链接:
http://blog.csdn.net/natian306/article/details/18504111
http://blog.csdn.net/fw0124/article/details/6672522

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值