synchronized关键字、ReentrantLock与原子类比较

我们先比较ReentrantLock与synchronized的用法
1、ReentrantLock拥有synchronized相同的并发性和内存语义,此外还多了锁投票,定时锁等候和中断等候。线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定。
使用synchronized时,如果A不释放,B将一直等待下去,无法中断。
使用ReentrantLock时,如果A不释放,B可以在等待足够长时间后,停止等待,继续执行其他事务。
ReentrantLock获取锁定的三种方式:
lock(),如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直至获取锁。
tryLock(),如果获取了锁立即返回true,如果别的线程下持有,立即返回false;
tryLock(long timeout, TimeUnit unit),如果获取了锁定立即返回true,如果别的线程正持有锁,将等待参数给定的时间,在等待的过程中,如果获取了锁定,返回true,如果等待超时,返回false,所以lock()方法相当trylock传递个无限大的时间参数;
lockInteruptibly,如果获取了锁定立即返回,反之,当前线程处理休眠,直至获取锁,或者当前线程线程被其他线程中断。
2、synchronized是在JVM层面实现,不但可以通过一些监控工具监控锁定,而且在代码执行出现异常,JVM自动释放锁定;
Lock是通过代码实现,为了保证锁定一定会被释放,一般会将unLock()放到flyinal{}中。
3、在资源竞争不激烈的情况下,synchronized的性能要优于ReentrantLock,但在资源竞争很激烈的情况下,synchronized的性能会下降几十倍(jvm需要分配额外的cpu和内存来管理同步),但是ReentrantLock的性能能维持常态。

ReentrantLock例子如下:
package test.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockTest1 extends Thread {

	private int threadNo;
	private static Lock lock = new ReentrantLock();

	public LockTest1(int threadNo) {
		this.threadNo = threadNo;
	}

	public static void main(String[] args) throws InterruptedException {
		for (int i = 0; i < 10; i++) {
			new LockTest1(i).start();
		}
	}

	@Override
	public void run() {
		lock.lock();
		try {
			for (int i = 0; i < 100; i++) {
				System.out.println("No." + (threadNo + 1) + ": " + (i + 1));
			}
		} finally {
			lock.unlock();
		}
	}
}

下面讨论原子类:
synchronized关键字、Lock可以控制程序片段的同步,原子类只能保证单个变量的同步。线程竞争不激烈时,原子类性能比synchronized略低,当竞争激烈时,也能维持常态。

下面是一个多线程共同计数的代码代码。
package test.lock;


public class LockTest2 extends Thread {

	private static int race = 0;
	private int threadNo;

	public LockTest2(int threadNo) {
		this.threadNo = threadNo;
	}

	public static void main(String[] args) throws InterruptedException {
		for (int i = 0; i < 10; i++) {
			new LockTest2(i).start();
		}

		while (Thread.activeCount() > 1) {
			Thread.yield();
		}
		System.out.println(race);
	}

	@Override
	public void run() {
		for (int i = 0; i < 1000; i++) {
			race++;
		}
	}
}
上面程序执行后,并没有得到期望的原子类。我们用ActomicInteger实现代码如下:
package test.lock;

import java.util.concurrent.atomic.AtomicInteger;

public class LockTest2 extends Thread {

	private static AtomicInteger race = new AtomicInteger();
	private int threadNo;

	public LockTest2(int threadNo) {
		this.threadNo = threadNo;
	}

	public static void main(String[] args) throws InterruptedException {
		for (int i = 0; i < 10; i++) {
			new LockTest2(i).start();
		}

		while (Thread.activeCount() > 1) {
			Thread.yield();
		}
		System.out.println(race);
	}

	@Override
	public void run() {
		for (int i = 0; i < 1000; i++) {
			race.addAndGet(1);
		}
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值