JAVA–线程的锁:synchronized与ReentrantLock 的区别和使用场景实例
1.说明:
synchronized:
是一个关键词,主要是对方法和代码块进行修饰,主要对会引起不安全的线程的进行处理,处理时需要考虑引起不安全的原因是由什么引起的。
对方法修饰:synchronized class 类名{}
对代码块进行修饰:synchronized (变量){代码块}
ReentrantLock
对代码块进行修饰,通过上锁和解锁两部来完成对线程的控制,通过try{} 来上锁执行代码块和 finally{}来解锁
2.区别:
synchronized 是隐形锁,ReentrantLock是显性锁,synchronized 比 ReentrantLock可以用于类的锁定,ReentrantLock只能可以用于代码块的上锁。
3.代码实例:
synchronized 的实现锁:
代码实现业务:两个人从一个账户进行取钱操作,账户金额只有100万
public class UnsSafetyOutMonney {
public static void main(String[] args) {
Acconunt acconunt=new Acconunt("结婚基金",100);
Drawing you=new Drawing(acconunt,50,"you");
Drawing youwife=new Drawing(acconunt,100,"youwife");
you.start();
youwife.start();
}
}
//创建账户
class Acconunt{
String name;
int Money;
public Acconunt(String name, int money) {
this.name = name;
Money = money;
}
}
//创建取钱操作类
class Drawing extends Thread{
//取钱的账户,实例化账户
Acconunt acconunt;
//取了多少钱
int DrawMoney;
//取钱的人
String name;
//现在手里有多少钱
int nowmoney=0;
public Drawing(Acconunt acconunt, int DrawMoney, String name){
super(name);
this.acconunt=acconunt;
this.DrawMoney=DrawMoney;}
@Override
public void run() {
//增加synchronized(){} 对acconunt进行监控,避免账户溢出
synchronized (acconunt){
if (acconunt.Money-DrawMoney<0){//判断取的钱是否大于账户余额 System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
return;
}
//sleep 间隔一段时间取钱
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//账户内余额=金额-取的钱
acconunt.Money= acconunt.Money-DrawMoney;
System.out.println(acconunt.name+"余额为"+acconunt.Money);
//更新手里的钱
nowmoney=nowmoney+DrawMoney;
System.out.println(this.getName()+"手上有"+nowmoney);
}
}
}
运行结果:
ReentrantLock 的实现锁:
实例代码
代码实现业务:只有十张票,同时有四个人来抢票
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
public static void main(String[] args) {
TestLock2 testLock2=new TestLock2();
new Thread(testLock2,"杨威").start();
new Thread(testLock2,"熊尼").start();
new Thread(testLock2,"张申").start();
new Thread(testLock2,"黄牛").start();
}
}
class TestLock2 implements Runnable{
int Tickets=100;
//实例化ReentrantLock类
ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
while (true){
try {
//调用上锁的命令
lock.lock();
if (Tickets>0){//当票的库存大于0时,开始抢票
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println(Thread.currentThread().getName()+"买到了第"+Tickets--);
}else {
break;
}
}finally {
//调用解锁的命令
lock.unlock();
}
}
}
}
运行结果: