Java线程安全问题以及死锁

/*
 * 举例:卖票
 * 假设,有10张票,分三个窗口同时卖
 * 
 * 1、线程安全问题:
 * 	当多个线程使用“共享数据”时,就会有线程安全问题。
 * 	当一个线程修改了“共享数据”,是会影响其他线程。
 * 
 * 2、如何解决?
 * 	加锁
 * 
 * 形式一:同步代码块
 * 形式二:同步方法
 * 
 * 3、同步代码块
 * 语法格式:
 * synchronized(锁对象){
 * 		需要加锁的代码
 * }
 * 
 * 锁对象,又称为监视器对象,同一时刻,某一段代码,只允许一个线程运行,这个锁就记录谁现在在运行,其他线程进不来。
 * 
 * 锁对象的选择:
 * (1)可以是任意类型的对象
 * (2)必须是这几天线程要使用同一个锁对象
 * 
 * 锁的代码的范围的选择:
 * (1)太大了:不行
 * (2)太小了:不行
 * 锁一次任务
 */
public class Test09 {
	public static void main(String[] args) {
		Ticket t1 = new Ticket("窗口一");
		Ticket t2 = new Ticket("窗口二");
		Ticket t3 = new Ticket("窗口三");
		
		t1.start();
		t2.start();
		t3.start();
	}
}
class Ticket extends Thread{
	private static int total = 1000;
	private static Object lock = new Object();//锁的选择之一,单独造一个锁对象
	
	public Ticket(String name) {
		super(name);
	}

	public void run(){
	//	synchronized (this) {//这里使用this不行,因为这个this,对于三个线程来说不是同一个
		while(true){
			synchronized (lock) {
				if(total > 0){
					System.out.println(getName() + "卖出一张票");
					total--;
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("剩余:" + total);
				}else{
					break;
				}
			}
		}
	}
}

/*
 * 步骤:
 * (1)编写线程类,实现Runnable
 * (2)重写run
 * (3)创建线程对象
 * (4)启动线程
 */
public class Test10 {
	public static void main(String[] args) {
		Ticket t = new Ticket();
		
		Thread t1 = new Thread(t,"窗口一");
		Thread t2 = new Thread(t,"窗口二");
		Thread t3 = new Thread(t,"窗口三");
		
		t1.start();
		t2.start();
		t3.start();
	}
}
class Ticket implements Runnable{
	private int total = 10;

	@Override
	public void run() {
		while(true){
			synchronized (this) {//选择this当锁,可以,因为只有一个Ticket的对象
				if(total>0){
					System.out.println(Thread.currentThread().getName() +"卖出一张票");
					total--;
					System.out.println("剩余:" + total);
				}else{
					break;
				}
			}
		}
	}
/*
 * 同步方法的语法格式:
 * 【修饰符】 synchronized 返回值类型  方法名(【形参列表】)throws 异常列表{
 * }
 * 
 * synchronized 【修饰符】  返回值类型  方法名(【形参列表】)throws 异常列表{
 * }
 * 
 * 同步方法的锁对象,程序员无法选择:
 * (1)非静态方法:this
 * (2)静态方法:当前类的Class对象
 */
public class Test11 {
	public static void main(String[] args) {
		Ticket t1 = new Ticket("窗口一");
		Ticket t2 = new Ticket("窗口二");
		Ticket t3 = new Ticket("窗口三");
		
		t1.start();
		t2.start();
		t3.start();
	}
}
class Ticket extends Thread{
	private static int total = 10;
	
	public Ticket(String name) {
		super(name);
	}

	public void run(){
		while(total>0){//程序停止的条件
			saleOneTicket();
		}
	}
	
	public synchronized static void saleOneTicket(){
		if(total > 0){//线程安全问题的条件
			System.out.println(Thread.currentThread().getName() + "卖出一张票");
			total--;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("剩余:" + total);
		}
	}
	
	//同步方法,锁的是方法的一次调用过程
	//非静态方法的锁对象是this,这里使用this,不是合格的锁对象
	/*public synchronized void saleOneTicket(){
		if(total > 0){//线程安全问题的条件
			System.out.println(getName() + "卖出一张票");
			total--;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("剩余:" + total);
		}
	}*/
}
public class Test12 {
	public static void main(String[] args) {
		Ticket t = new Ticket();
		
		Thread t1 = new Thread(t,"窗口一");
		Thread t2 = new Thread(t,"窗口二");
		Thread t3 = new Thread(t,"窗口三");
		
		t1.start();
		t2.start();
		t3.start();
	}
}
class Ticket implements Runnable{
	private int total = 10;

	@Override
	public void run() {
		while(total>0){
			saleOneTicket();
		}
	}
	//当前同步方法的锁对象是this,可以的,因为只有一个Ticket
	public synchronized void saleOneTicket(){
		if(total>0){
			System.out.println(Thread.currentThread().getName() +"卖出一张票");
			total--;
			System.out.println("剩余:" + total);
		}
	}
}

死锁问题:

/*
 * 死锁:
 *   两个线程,互相持有,占有对方想要的锁,不放手。
 */
public class TestDeadLock {
	public static void main(String[] args) {
		Object g = new Object();
		Object m = new Object();
		
		Boy b = new Boy(g,m);
		Bang bang = new Bang(g,m);
		
		b.start();
		bang.start();
	}
}
//男朋友
class Boy extends Thread{
	private Object girl;
	private Object money;
	
	public Boy(Object girl, Object money) {
		super();
		this.girl = girl;
		this.money = money;
	}

	public void run(){
		synchronized (money) {
			System.out.println("你放了我女朋友,我给你500万");
			synchronized (girl) {
				System.out.println("给了对方500万");
			}
		}
	}
}
//绑匪
class Bang extends Thread{
	
	private Object girl;
	private Object money;
	
	public Bang(Object girl, Object money) {
		super();
		this.girl = girl;
		this.money = money;
	}

	public void run(){
		synchronized (girl) {
			System.out.println("你给我500万,我放了你女朋友");
			synchronized (money) {
				System.out.println("放人");
			}
		}
	}
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值