《ReentrantLock与synchronized的区别》

目录

Synchronized同步锁

synchronized的用法:

ReentrantLock

ReentrantLock和Synchronized的区别


 

Synchronized同步锁

        使用Synchronized关键字将一段代码锁起来,同一时间只允许一个线程访问。只有获取了这把锁的线程才能访问这段代码,并且只有一个线程拥有这把锁。这样就保证了代码的安全性。

synchronized的用法:

        1.修饰实例方法:synchronized修饰实例方法,则用到的锁,默认为this当前方法调用对象。

        只有获取this锁的线程才能访问当前方法。同一时刻只有一个线程持有this锁。

	public synchronized void add() {
		
	}
	public void add1() {
	    synchronized(this) {
			
		}
	}
//使用synchronized关键字修饰方法时,两种写法作用与意义相同

        2.修饰静态方法 :修饰静态方法,用到的锁,默认为当前类的Class对象

	public synchronized static void add() {
		
	}

        3.修饰代码块:修饰代码块,用到的锁是可以指定的,为指定的某类对象。        

	Object obj = new Object();
	public void de() {
		synchronized(obj) {
			
		}
	}

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

        父类中synchronized修饰的方法,如果子类没有重写,,则该方法仍然是线程安全的;如果子类重写,并没有使用synchronized修饰,则该方法是线程不安全的。

        定义接口方法时,不能使用synchronized关键字;

        构造方法不能使用synchronized关键字,但是可以使用synchronized代码块来进行同步。

        离开synchronized代码块后,该线程持有的锁,自动释放。

ReentrantLock

        ReentrantLock是Java中一种可重入锁。

        重入锁:一个线程,在获取锁后,可以继续获取同一个锁

                

public class Counter {
    private int count = 0;

    public synchronized void add(int n) {
        if (n < 0) {
            dec(-n);
        } else {
            count += n;
        }
    }

    public synchronized void dec(int n) {
        count += n;
    }
}
//当执行add()方法后,会继续调用dec()方法,dec方法也需要获取this锁。

         JVM允许同一个线程重复获取同一个锁,这种能被反复获取的锁,叫可重入锁。

        ReentrantLock是可重入锁,synchronized也是可重入锁。

        在获取可重入锁时,要记录这是第几次获取,没获取一次记录+1,每次退出可重入锁,记录-1,减到0时,才会真正释放锁。

public class Counter {
    private final Lock lock = new ReentrantLock();
    private int count;

    public void add(int n) {
        lock.lock();
        try {
            count += n;
        } finally {
            lock.unlock();
        }
    }
}

        ReentrantLock是JavaSE 核心类库的并发包(java.util.concurrent)提供的可重入锁,所以以防有异常发生,无法正常释放锁所以在创建锁后,在finally中释放锁。

        ReentrantLock还可以尝试获取锁:

                

if (lock.tryLock(1, TimeUnit.SECONDS)) {
    try {
        ...
    } finally {
        lock.unlock();
    }
}

尝试获取锁,最多等待一秒。一秒后,还未获取到锁,直接返回false,程序可以尝试做一些额外的处理,而不是无线等待。

        所以,ReentrantLock比synchronized更安全,在使用tryLock()失败后不会产生死锁。 

  ReentrantLock内部有三个类:Sync、NonfairSync、FairSync。

        NonfairSync类继承了Sync类,表示采用非公平策略获取锁:每一次都尝试获取锁,不会按照公平等待的原则进行等待,不会让等待最久的线程获得锁。

        FairSync类也继承了 Sync类,表示采用公平策略获取锁:当资源空闲时,它总是会先判断 sync队列是否有等待时间更长的线程,如果存在,则将当前线程加入到等待队列的尾部,实现了公平获取原则。

        ReentrantLock构造函数:默认是采用的非公平策略获取锁。

        ReentrantLock(boolean) 构造函数:可以传递参数确定采用公平策略或者是非公平策略,参数为 true表示公平策略,否则,采用非公平策略。

ReentrantLock和Synchronized的区别

        

ReentrantLockSynchronized
锁实现机制AQS监视器Monitor
获取锁可以通过tryLock()尝试获取锁,更灵活线程抢占模型
释放锁必须显示通过unlock()释放锁自动释放
锁类型支持公平锁和非公平锁非公平锁
可重入性可重入可重入

                

         

     

 

 

        

 

         

 

     

         

 

   

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NiKo_.gg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值