并发:同一个对象被多个线程同时操作
处理多线程问题时,常会遇到多个线程访问同一个对象的情况,并且其中的某些线程还需要对这个对象进行修改。这时就需要线程同步,以避免数据出错。
代码
package com.pbx.lesson02;
/**
* 模拟两个人同时从一个银行账户中取钱
*
* @author BruceXu
* @date 2020/9/13
*/
public class ThreadNotSync {
public static void main(String[] args) {
Account account = new Account("棺材本", 100);
new Bank(account, 50, "我").start();
new Bank(account, 100, "老婆").start();
}
}
class Account {
String name;
int Money;
public Account(String name, int Money) {
this.name = name;
this.Money = Money;
}
}
class Bank extends Thread {
private final Account account;
private final int drawing;
private int currentMoney = 0;
public Bank(Account account, int drawing, String name) {
super(name);
this.account = account;
this.drawing = drawing;
}
// 取钱
@Override
public void run() {
// 判断还有钱吗
if (account.Money - drawing < 0) {
System.out.println("没钱了,别取了" + this.getName());
return;
}
//模拟延迟
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.Money -= drawing;
currentMoney += drawing;
// 结果查看
System.out.println(this.getName() + "取了:" + drawing + ",账户还剩:" + account.Money);
}
}
结果
出现了负数,也就是说不符合实际情况的。
内存分析
描述:
产生死锁的四个必要条件:
避免:破坏上述条件中的任意一个或多个
从JDK 5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当
java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象
ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁。
代码示例
class A {
private final ReentrantLock lock = new ReenTrantLock();
public void m(){
// 上锁,锁定资源
lock.lock();
try{
//保证线程安全的代码;
}
finally{
// 解锁、释放资源
lock.unlock();
//如果同步代码有异常,要将unlock()写入finally语句块
}
}
}
package com.pbx.lesson02;
/**
* 模拟两个人同时从一个银行账户中取钱
*
* @author BruceXu
* @date 2020/9/13
*/
public class ThreadNotSync {
public static void main(String[] args) {
Account account = new Account("棺材本", 100);
new Bank(account, 50, "我").start();
new Bank(account, 100, "老婆").start();
}
}
class Account {
String name;
int Money;
public Account(String name, int Money) {
this.name = name;
this.Money = Money;
}
}
class Bank extends Thread {
private final Account account;
private final int drawing;
private int currentMoney = 0;
public Bank(Account account, int drawing, String name) {
super(name);
this.account = account;
this.drawing = drawing;
}
// 取钱
@Override
public void run() {
// synchronized 加锁原则:谁要被改,给谁加锁
synchronized (account) {
// 判断还有钱吗
if (account.Money - drawing < 0) {
System.out.println("没钱了,别取了" + this.getName());
return;
}
//模拟延迟
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.Money -= drawing;
currentMoney += drawing;
// 结果查看
System.out.println(this.getName() + "取了:" + drawing + ",账户还剩:" + account.Money);
}
}
}
原文:https://www.cnblogs.com/primabrucexu/p/13694072.html