一,解决线程安全问题--加锁
1,synchronized 自动锁
synchronized () {}
()锁资源-----共享资源作为锁资源.只要使用的是同一把锁资源就可以上锁成功。必须是对象可以是(this或Object)
public class TestTicket {
public static void main(String[] args) {
Ticket task=new Ticket();//任务对象
Thread t1=new Thread(task,"窗口A");
Thread t2=new Thread(task,"窗口B");
Thread t3=new Thread(task,"窗口C");
Thread t4=new Thread(task,"窗口D");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Ticket implements Runnable {
private Integer ticket = 100;
private Object o=new Object(); //新建一个Object做为锁资源
@Override
public void run() {
while (true) {
synchronized (this) { //()要的是一个对象! tiket它是一个int类型
if (ticket <= 0) {
break;
}
ticket--;
System.out.println(Thread.currentThread().getName() + "卖了一张,剩余:" + ticket + "张");
}
}
}
}
Lock 手动锁
Lock lock = new ReentrantLock();
lock.lock(); 加锁
lock.unlock();解锁
/**
* @program: thread02
* @description:
* @author: 坤仔
* @create: 2022-01-05 15:57
**/
public class Testhelloworld {
private static String[] arr=new String[5];
private static int index=0;
public static void main(String[] args) throws InterruptedException {
Lock lock = new ReentrantLock();
Runnable hello = new Runnable(){
@Override
public void run() {
try {
lock.lock();//重入锁 可以多次加锁,创建一个手动锁对象
if (arr[index]==null){
arr[index]="hello";
index++;
}
} finally {
lock.unlock();//解锁
}
}
};
Runnable world = new Runnable(){
@Override
public void run() {
try {
lock.lock();
if (arr[index]==null){
arr[index]="world";
index++;
}
} finally {
lock.unlock();
}
}
};
Thread t1 = new Thread(hello, "AAA");
Thread t2 = new Thread(world, "BBB");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(Arrays.toString(arr));
}
}
二,死锁以及如何避免死锁
如何避免
1.尽量不要使用锁的嵌套。
2.尽量使用安全类。
3.可以lock锁的tryLock设置锁的时间。
三,线程通信
唤醒 notify() 随机唤醒等待队列中的一个; notifyAll() 唤醒等待队列中的所有线程
一存一取
/**
* @program: thread02
* @description:
* @author: 坤仔
* @create: 2022-01-05 16:22
**/
public class TestBank {
public static void main(String[] args) {
Banck banck = new Banck(0);
saveMoney saveMoney = new saveMoney(banck);
takeMoney takeMoney = new takeMoney(banck);
Thread t1= new Thread(saveMoney, "AAA");
Thread t2 = new Thread(takeMoney, "BBB");
t1.start();
t2.start();
}
}
class saveMoney implements Runnable{
private Banck banck;
public saveMoney(Banck banck) {
this.banck = banck;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
banck.savemoney(1000);
}
}
}
class takeMoney implements Runnable{
private Banck banck;
public takeMoney(Banck banck) {
this.banck = banck;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
banck.takemoney(1000);
}
}
}
class Banck{
private double balnce;
private boolean flag=false;
public Banck(double balnce) {
this.balnce = balnce;
}
public synchronized void savemoney(double money){
if (flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
balnce+=1000;
System.out.println(Thread.currentThread().getName()+"存入了1000元;卡中余额:"+balnce);
flag=true;
this.notify();
}
public synchronized void takemoney(double money){
if (!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
balnce-=1000;
System.out.println(Thread.currentThread().getName()+"取出了1000元;卡中月"+balnce);
flag=false;
this.notify();
}
}
多存多取
/**
* @program: thread02
* @description:
* @author: 坤仔
* @create: 2022-01-05 16:22
**/
public class TestBank {
//多存多取 出现余额变为负数的问题 解决方案 把if改为while 每次唤醒都做判断
public static void main(String[] args) {
Banck banck = new Banck(0);
saveMoney saveMoney = new saveMoney(banck);
takeMoney takeMoney = new takeMoney(banck);
Thread t1= new Thread(saveMoney, "AAA");
Thread t2 = new Thread(takeMoney, "BBB");
Thread t3= new Thread(saveMoney, "CCC");
Thread t4 = new Thread(takeMoney, "DDD");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class saveMoney implements Runnable{
private Banck banck;
public saveMoney(Banck banck) {
this.banck = banck;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
banck.savemoney(1000);
}
}
}
class takeMoney implements Runnable{
private Banck banck;
public takeMoney(Banck banck) {
this.banck = banck;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
banck.takemoney(1000);
}
}
}
class Banck{
private double balnce;
private boolean flag=false;
public Banck(double balnce) {
this.balnce = balnce;
}
public synchronized void savemoney(double money){
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
balnce+=1000;
System.out.println(Thread.currentThread().getName()+"存入了1000元;卡中余额:"+balnce);
flag=true;
this.notify();
}
public synchronized void takemoney(double money){
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
balnce-=1000;
System.out.println(Thread.currentThread().getName()+"取出了1000元;卡中月"+balnce);
flag=false;
this.notify();
}
}
结果
结果
if改为while
public class TestBank {
//多存多取 出现余额变为负数的问题 解决方案 把if改为while 每次唤醒都做判断
public static void main(String[] args) {
Banck banck = new Banck(0);
saveMoney saveMoney = new saveMoney(banck);
takeMoney takeMoney = new takeMoney(banck);
Thread t1= new Thread(saveMoney, "AAA");
Thread t2 = new Thread(takeMoney, "BBB");
Thread t3= new Thread(saveMoney, "CCC");
Thread t4 = new Thread(takeMoney, "DDD");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class saveMoney implements Runnable{
private Banck banck;
public saveMoney(Banck banck) {
this.banck = banck;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
banck.savemoney(1000);
}
}
}
class takeMoney implements Runnable{
private Banck banck;
public takeMoney(Banck banck) {
this.banck = banck;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
banck.takemoney(1000);
}
}
}
class Banck{
private double balnce;
private boolean flag=false;
public Banck(double balnce) {
this.balnce = balnce;
}
public synchronized void savemoney(double money){
while (flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
balnce+=1000;
System.out.println(Thread.currentThread().getName()+"存入了1000元;卡中余额:"+balnce);
flag=true;
this.notify();
}
public synchronized void takemoney(double money){
while (!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
balnce-=1000;
System.out.println(Thread.currentThread().getName()+"取出了1000元;卡中月"+balnce);
flag=false;
this.notify();
}
}
结果:
改善 使用notifyAll替换notify
/**
* @program: thread02
* @description:
* @author: 坤仔
* @create: 2022-01-05 16:22
**/
public class TestBank {
//多存多取 出现余额变为负数的问题 解决方案 把if改为while 每次唤醒都做判断
public static void main(String[] args) {
Banck banck = new Banck(0);
saveMoney saveMoney = new saveMoney(banck);
takeMoney takeMoney = new takeMoney(banck);
Thread t1= new Thread(saveMoney, "AAA");
Thread t2 = new Thread(takeMoney, "BBB");
Thread t3= new Thread(saveMoney, "CCC");
Thread t4 = new Thread(takeMoney, "DDD");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class saveMoney implements Runnable{
private Banck banck;
public saveMoney(Banck banck) {
this.banck = banck;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
banck.savemoney(1000);
}
}
}
class takeMoney implements Runnable{
private Banck banck;
public takeMoney(Banck banck) {
this.banck = banck;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
banck.takemoney(1000);
}
}
}
class Banck{
private double balnce;
private boolean flag=false;
public Banck(double balnce) {
this.balnce = balnce;
}
public synchronized void savemoney(double money){
while (flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
balnce+=1000;
System.out.println(Thread.currentThread().getName()+"存入了1000元;卡中余额:"+balnce);
flag=true;
this.notifyAll();
}
public synchronized void takemoney(double money){
while (!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
balnce-=1000;
System.out.println(Thread.currentThread().getName()+"取出了1000元;卡中月"+balnce);
flag=false;
this.notifyAll();
}
}