线程同步锁:隐式synchronized,显式lock,懒汉设计模式加锁,死锁

线程同步
1.隐式同步锁synchronized
1.同步代码块
2.同步方法
同步方法 必须放在 资源类中,确保this 只有一份
有锁, 但是锁默认是 this
非静态同步方法, 锁是 this, 静态同步方法,锁 是 类.class

1.有五个人同时过一个独木桥,一个独木桥同时只能允许一个人通过。每一个人通过独木桥的时间是随机在 [5,10] 秒,输出这个独木桥上每一个人的通过详情,
例如:张三开始过独木桥了… 张三通过独木桥了!
1.同步代码块

public class Test {
    
    
	public static void main(String[] args) {
    
    
		Bridge t = new Bridge();
		Thread t1 = new Thread(t, "张三");
		Thread t2 = new Thread(t, "李四");
		Thread t3 = new Thread(t, "王五");
		Thread t4 = new Thread(t, "赵六");
		Thread t5 = new Thread(t, "田七");
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
	}
}
class Bridge implements Runnable {
    
    
	@Override
	public void run() {
    
    
		synchronized (this) {
    
    
			System.out.println(Thread.currentThread().getName() + "开始过独木桥了");
			int num = (int) (Math.random() * 6 + 5);
			try {
    
    
				Thread.sleep(num * 1000);
			} catch (InterruptedException e) {
    
    
				e.printStackTrace();				
			}
			System.out.println(Thread.currentThread().getName() + "通过独木桥了");			
		}
	}
}

在这里插入图片描述
2.同步方法

public class Test {
    
    
	static Object obj = new Object();
	public static void main(String[] args) {
    
    
		Qiao t = new Qiao();
		Thread t1 = new Thread(t, "张三");
		Thread t2 = new Thread(t, "李四");
		Thread t3 = new Thread(t, "王五");
		Thread t4 = new Thread(t, "赵六");
		Thread t5 = new Thread(t, "田七");
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
	}
}
class Qiao implements Runnable {
    
    
	@Override
	public void run() {
    
    
		bridge();
	}
	public static synchronized void bridge() {
    
    
		// Qiao.class 永远唯一, 符合锁的要求
		System.out.println(Thread.currentThread().getName() + "开始过桥了");
		int i = (int) (Math.random() * (10 - 5 + 1) + 5);
		try {
    
    
			Thread.sleep(i * 1000);// 会释放cpu, 但是不会释放锁
		} catch (InterruptedException e) {
    
    
// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName() + "过去了");
	}
}

在这里插入图片描述
例:2.有一张银行卡, 张三,李四所有,张三 往里边存钱 每次存10000,一共存10次,李四 取钱, 每次取10000, 一共取10次
同步代码块

public class Test {
    
    
	public static void main(String[] args) {
    
    
		Card card = new Card();
		Zs zs = new Zs(card);
		Ls ls = new Ls(card);
		Thread thread = new Thread(zs);
		Thread thread2 = new Thread(ls);
		thread.start();
		thread2.start();
	}
}
class Card {
    
    
	int money;
	public Card(int money) {
    
    
		super();
		this.money = money;
	}
	public Card() {
    
    
		super();
	}
}
class Zs implements Runnable {
    
    
	Card card;
	public Zs(Card card) {
    
    
		super();
		this.card = card;
	}
	@Override
	public void run() {
    
    
		for (int i = 0; i < 10; i++) {
    
    
			synchronized (card) {
    
    
				card.money += 10000;
				System.out.println("张三存了10000,还剩" + card.money);
			}
		}
	}
}
class Ls implements Runnable {
    
    
	Card card;
	public Ls(Card card) {
    
    
		super();
		this.card = card;
	}
	@Override
	public void run() {
    
    
		for (int i = 0; i < 10; i++) {
    
    
			synchronized (card) {
    
    
				card.money -= 10000;
				System.out.println("李四取了10000,还剩" + card.money);
			}
		}
	}
}

在这里插入图片描述
同步方法

public class Test2 {
    
    
	public static void main(String[] args) {
    
    
		Card2 card = new Card2();
		Zs2 zs2 = new Zs2(card);
		Ls2 ls2= new Ls2(card);
		Thread thread = new Thread(zs2);
		Thread thread2 = new Thread(ls2);
		thread.start();
		thread2.start();
	}
}
// 资源类
class Card2 {
    
    
	int money;
	public synchronized void take() {
    
    // this
		money -= 10000;
		System.out.println("李四取了10000,还剩" + money);
	}
	public synchronized void save() {
    
    // this
		money += 10000;
		System.out.println("张三存了10000,还剩" + money);
	}
}
// 操作类
class Zs2 implements Runnable {
    
    
	Card2 card;
	public Zs2(Card2 card) {
    
    
		super();
		this.card = card;
	}
	@Override
	public void run() {
    
    
		for (int i = 0; i < 10; i++) {
    
    
			card.save();
		}
	}
}
// 操作类
class Ls2 implements Runnable {
    
    
	Card2 card;
	public Ls2(Card2 card) {
    
    
		super();
		this.card = card;
	}
	@Override
	public void run() {
    
    
		for (int i = 0; i < 10; i++) {
    
    
			card.take();
		}
	}
}

在这里插入图片描述
2.显式同步锁Lock
需要手动new出对象,只能有一个对象
需要解锁,lock.unlock
加try-finally,目的是为了一定进行解锁

import java.util.concurrent.locks.ReentrantLock;
public class Test {
    
    
	public static void main(String[] args) {
    
    
		//创建一次资源类对象
		Ticket ticket = new Ticket();		
		//创建线程对象
		Thread t = new Thread(ticket, "窗口一");
		Thread t2 = new Thread(ticket, "窗口二");
		Thread t3 = new Thread(ticket, "窗口三");
		Thread t4 = new Thread(ticket, "窗口四");		
		t.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
class Ticket implements Runnable{
    
    
	int ticket = 100;
	ReentrantLock lock = new ReentrantLock();
	@Override
	public void run() {
    
    
		while (true) {
    
    
			try {
    
    
				//开始加锁
				lock.lock();
				if (ticket>0) {
    
    
					ticket--;
					System.out.println(Thread.currentThread().getName()+"买了一张票,还剩"+ticket+"张票");
				}else {
    
    
					break;
				}
			} finally {
    
    
				// 解锁
				lock.unlock();
			}
		}
	}
}

在这里插入图片描述
3.懒汉设计模式加锁
每个类的模板都是唯一的
添加了一把锁,做了双重检查(虽然加了一把锁,但是做了双重检查,外层检查目的是提高执行效率)

public class LazyInstance {
    
    
	private LazyInstance() {
    
    		
	}
	private static LazyInstance instance = null;
	public static LazyInstance getInstance() {
    
    
		if (instance == null) {
    
    
			synchronized (LazyInstance.class) {
    
    
				if (instance == null) {
    
    
					instance = new LazyInstance();
				}
			}
		}
		return instance;
	}
}

在这里插入图片描述

4.死锁
两个(多个线程)持有着对方想要的资源不放,但是还想要对方手里的资源
写代码的时候一定要避免
如果遇到需要有同步代码块嵌套的情况, 持有锁的顺序应该一致

public class Test {
    
    
	public static void main(String[] args) {
    
    
		Zs zs = new Zs();
		Ls ls = new Ls();
		zs.start();
		ls.start();		
	}
}
class Lock{
    
    
	static Object locka = new Object();
	static Object lockb = new Object();
}
class Zs extends Thread{
    
    
	@Override
	public void run() {
    
    		
		synchronized (Lock.locka) {
    
    
			System.out.println("张三拥有了筷子a,准备去抢筷子b");
			synchronized(Lock.lockb) {
    
    
				System.out.println("张三抢到了两根筷子,张三吃饭");
			}
		}
	}
}
class Ls extends Thread{
    
    
	@Override
	public void run() {
    
    		
		synchronized (Lock.locka) {
    
    
			System.out.println("李四拥有了筷子a,准备去抢筷子b");
			synchronized(Lock.lockb) {
    
    
				System.out.println("李四抢到了两根筷子,张三吃饭");
			}
		}
	}
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Echoxxxxx/article/details/112942341