锁的两个基本工具—synchronized和Lock

1.ReentrantLock synchronized相同的并发性和内存语义,还包含了中断锁等候和定时锁等候,意味着线程A如果先获得了对象obj的锁,那么线程B可以在等待指定时间内依然无法获取锁,那么就会自动放弃该锁。
2.但是由于synchronized是在JVM层面实现的,因此系统可以监控锁的释放与否,而ReentrantLock使用代码实现的,系统无法自动释放锁,需要在代码中finally子句中显式释放锁lock.unlock();
3.使用建议:
在并发量比较小的情况下,使用synchronized是个不错的选择,但是在并发量比较高的情况下,其性能下降很严重,此时ReentrantLock是个不错的方案。
看下lock的具体使用,如下代码:
package thread.lock;

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

/**
 * 共享实体
 * 
 * @author admin
 * 
 */
class Person {
	public String name;
	public String sex;
	/*
	 * 默认是false。。 flag为false 生产者生产---消费者等待 flag为true 生产者等待---消费者消费
	 */
	public boolean flag = false;

	Lock lock = new ReentrantLock();
}

/**
 * 生产者
 * 
 * @author admin
 * 
 */
class Write extends Thread {
	int count = 0;
	Person per = new Person();
	Condition newCondition;

	public Write(Person p, Condition newCondition) {
		this.per = p;
		this.newCondition = newCondition;
	}

	@Override
	public void run() {
		while (true) {
			try {
				// 开启锁
				per.lock.lock();
				if (per.flag) {
					try {
						newCondition.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				} else {
					if (count == 0) {
						per.name = "yhl";
						per.sex = "男";
					} else {
						per.name = "xyf";
						per.sex = "女";
					}
					count = (count + 1) % 2;// 奇偶数计算
					per.flag = true;// 设置为ture;让生产者等待,通知让消费者消费去
					newCondition.signal();// 通知
				}
			} catch (Exception e) {
				// TODO: handle exception
			} finally {
				per.lock.unlock();
			}
		}
	}

}

/**
 * 消费者
 * 
 * @author admin
 * 
 */
class Read extends Thread {
	Person per = new Person();
	Condition newCondition;

	public Read(Person p, Condition newCondition) {
		this.per = p;
		this.newCondition = newCondition;
	}

	@Override
	public void run() {
		while (true) {
			try {
				// 开启锁
				per.lock.lock();
				if (!per.flag) {
					try {
						newCondition.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				} else {
					System.out.println("name:" + per.name + ",sex:" + per.sex);
					per.flag = false;// 设置为false 让消费者处于等待,生产者去生产
					newCondition.signal();//通知
				}
			} catch (Exception e) {
				// TODO: handle exception
			} finally {
				per.lock.unlock();
			}

		}
	}
}

public class LockReadWrite {
	public static void main(String[] args) {
		Person p = new Person();
		Condition newCondition = p.lock.newCondition();
		Write w = new Write(p, newCondition);
		Read r = new Read(p, newCondition);
		w.start();
		r.start();
	}
}

总结来说,Lock和synchronized有以下几点不同:
  1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
  2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
  3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
  4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
  5)Lock可以提高多个线程进行读操作的效率。
  在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值