多线程-并发与锁

我们讲到多线程,就离不开并发,讲到并发,就离不开安全性,这里我们先来实现一个简单功能能:买票系统

 

这是票的类,以及买票的方法:

public class DBTicket {
	// 假设存放100张票
	private static int num = 100;
	public static void setNum(int num) {
		DBTicket.num = num;
	}
	// 这是一个买票的方法
	public static  int getTicket(){
		if(num < 1){
			return 0;
		}
		return num --;
	}
}

 这是一个线程,模拟一个卖票窗口:

public class Thread1 implements Runnable {
	@Override
	public void run() {
		// 打印哪个窗口(线程),买到哪张票
		System.out.println(Thread.currentThread() +":"+DBTicket.getTicket());
	}
}

 

 模拟买票:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
	public static void main(String[] args) throws Exception {
		ExecutorService ex = Executors.newFixedThreadPool(10);
		// 通过线程池, 模拟有3个窗口(线程),当然你可以建立不同的Thread 1 2 3
		// 多执行几次
		for(int i = 0;i<3;i++){
			ex.execute(new Thread1());
			ex.execute(new Thread1());
			ex.execute(new Thread1());
		}
		ex.shutdown();
	}
}

 当你多执行几次的时候发现,会有重复的数字,不同的创窗口(线程),买到同样的票!你显然不不允许的。

OK,这是时候 很多人会说,加上关键字,synchronized ,就行了。是的,加上了 目前是安全的。

	public static synchronized  int getTicket(){
		if(num < 1){
			return 0;
		}
		return num --;
	}

 

提示:这里加上 Thread.sleep(100) 模拟买票需要时间,效果更明显。

 

这里可以用java.util.concurrent.* 下面的 ReentrantLock 进行锁定;比如:

 

	private void lookStatus(){
		try{
			lock.lock();
			int num  = getNum();
			// 打印哪个窗口(线程),买到哪张票
			System.out.println(Thread.currentThread() +":"+num);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}

 

这里记得关闭 ,unlock 方法。不然会持有锁,不放的。具体请看API  或者源码,此类更更灵活。

发现内容比较多。还是整理一下,单独说线程的类吧

你可能感兴趣的:(并发,线程,synchronized,同步,锁)