用锁解决线程同步问题

一:synchronized 隐形锁

属于排它锁。
1、synchronized 锁类使得多个对象有序的调用一个run方法
举例:
问题描述:火车站卖票系统,火车站有多个售票窗口,每张票都有自己的编号,不同的窗口同时卖票,不可以在不同的窗口卖出同一张票。
首先有一个票类:用来存储车票的信息。

public class Ticket {
private String tno;

public Ticket(String tno) {
	this.tno=tno;
}

public String getTno() {
	return tno;
}

public void setTno(String tno) {
	this.tno = tno;
}

}

要有窗口类:用来售票。

public class Windows implements Runnable {
private LinkedList<Ticket> tickest=new LinkedList<>();//将窗口类和票类关联
public  Windows(LinkedList<Ticket> tickest) {
	this.tickest=tickest;
}
//run中使用任何锁都不会达到同步效果,因为有多个window对象
@Override
 public  void run() {
	// TODO Auto-generated method stub
	while(true) {
		try {
			shell(tickest);
			Thread.sleep(200);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}
//卖票   此处必须是static方法,否则三个window,会调三个不同的run(),在run()中使用锁是无效的
synchronized public static void shell(LinkedList<Ticket> tickest) {
	if(tickest.size()>0) {
		Ticket t=tickest.removeLast();
		System.out.println(Thread.currentThread().getId()+"卖了一张票"+t.getTno());
	}
	
}

}

测试类:
假设有100张车票,用LinkedList的原因是底层实现为链表,删除时方便

public class Test {
public static void main(String[] args) {
	LinkedList<Ticket> ts = new LinkedList<>();
	for(int i=0;i<100;i++) {
		Ticket t = new Ticket(Integer.toString(i));
		ts.add(t);
	}
		new Thread(new Windows(ts)).start();
		new Thread(new Windows(ts)).start();
		new Thread(new Windows(ts)).start();
}
}

测试结果:

10卖了一张票99
11卖了一张票98
12卖了一张票97
12卖了一张票96
11卖了一张票95
10卖了一张票94
11卖了一张票93
12卖了一张票92
10卖了一张票91
12卖了一张票90
	.
	.
	.
12卖了一张票3
11卖了一张票2
10卖了一张票1
12卖了一张票0

注意: 非static方法使用synchronized ,本质是给当前对象加锁
2、synchronized 俩把锁问题
问题描述:花园洋房有大门和屋门来个门,一群人想要进入屋子必须先进入大门,然后进入屋门,要求在进大门的时候不妨碍进屋门。

public class GradenHouse{
	private Object obj1=new Object();
	private Object obj2=new Object();
  public void openDoor() {

		 synchronized(obj1) {
			 System.out.println(Thread.currentThread().getId()+"开大门");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getId()+"进大门");
		 }
	
	
}
 public void openRoom() {
	 synchronized(obj2) {
		 System.out.println(Thread.currentThread().getId()+"。。。。。开屋门");
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getId()+"。。。。。进屋门");
	 }
	
}

}
public class Test {
public static void main(String[] args) {
	ExecutorService pool=Executors.newCachedThreadPool();
	GradenHouse gh=new GradenHouse();
	for(int i=0;i<100;i++) {
		pool.execute(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				gh.openDoor();
				gh.openRoom();
			}
		});
	}
}
}

执行结果:

10。。。。。开屋门
10。。。。。进屋门
109进大门
109。。。。。开屋门
108开大门
109。。。。。进屋门
108进大门
107开大门
108。。。。。开屋门
107进大门
108。。。。。进屋门
107。。。。。开屋门
106开大门
107。。。。。进屋门
	.
	.
	.

二:ReentrantLock 重入锁

属于排它锁。
举例:还是上面那个换能源洋房问题。

public class GradenHouse{
	private ReentrantLock doorLock;
	private ReentrantLock roomLock;
	public GradenHouse() {
		doorLock=new ReentrantLock();
		roomLock=new ReentrantLock();
	}
/**
 * 一次只能有一个人进入大门
 */
public void openDoor() {
	try {
		doorLock.lock();//获得锁。
		System.out.println(Thread.currentThread().getId()+"开大门");
		try {
			Thread.sleep(200);
		} catch (Exception e) {
			// TODO: handle exception
		}
		System.out.println(Thread.currentThread().getId()+"进大门");
	} finally {
		doorLock.unlock();//释放锁
	}
}
public void openRoom() {
	try {
		roomLock.lock();
		System.out.println(Thread.currentThread().getId()+"开屋门");
		try {
			Thread.sleep(200);
		} catch (Exception e) {
			// TODO: handle exception
		}
		System.out.println(Thread.currentThread().getId()+"进屋门");
	} finally {
		roomLock.unlock();
	}
}
}
public class Test {
public static void main(String[] args) {
	ExecutorService pool=Executors.newCachedThreadPool();
	GradenHouse gh=new GradenHouse();
	for(int i=0;i<100;i++) {
		pool.execute(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				gh.openDoor();
				gh.openRoom();
			}
		});
	}
}
}

执行结果:

10开大门
10进大门
10开屋门
12开大门
10进屋门
12进大门
11开大门
12开屋门
12进屋门
11进大门
11开屋门
13开大门
13进大门
11进屋门
	.
	.
	.

void lock() 获得锁。
void unlock() 尝试释放此锁。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值