线程同步的三种方案

原创 2015年11月20日 17:34:59

以电影院售票为例

方案一:同步代码块

public class Cinerma {
	int tickets = 50;//剩余票数
	Object lock = new Object();//可以看做钥匙对象
//卖票函数
 public void  sellTicket(int num,int id) throws InterruptedException {//本函数一般跑在子线程中,所以在执行tickets = tickets -num;时会发生线程危险
		
		
	if(tickets>=num){
            System.out.println(Thread.currentThread().getName()+id+":啊哈,有票,让我来跟售票员墨迹一会");//注意此处子线程的id
            Thread.sleep(200);
            System.out.println(Thread.currentThread().getName()+id+":墨迹完了,我要买票了");
            synchronized(lock){//正式买票,同步起来
                
                if(tickets>=num){
                    Thread.sleep(200);
                    tickets = tickets -num;
                    System.out.println(Thread.currentThread().getName()+id+":买了"+num+"张,剩余票数"+tickets);
                }else{
                    System.out.println(Thread.currentThread().getName()+id+":fuck=fuck=fuck=fuck=fuck,刚刚还有票的");
                }
            
            }
        }else{
            System.out.println("没票了咱走吧");
        }
        


方案二:使用加锁对象,ReentrantLock


        ReentrantLock reentrantLock = new ReentrantLock();//放在成员里就好
	//询问处的函数,一次只能一个线程来问,都排队
	public void question(int id) throws InterruptedException{//运行在子线程中的方法
		reentrantLock.lock();//此处开始同步
		System.out.println(Thread.currentThread().getName()+id+":来买爆米花了");
		Thread.sleep(3000);
		System.out.println(Thread.currentThread().getName()+id+":买完了");
		reentrantLock.unlock();//此处停止同步
	}

调用方法:

Cinerma cinerma = new Cinerma();
		
		Thread buyticketThread1 = new BuyTicketThread("情侣", 2, cinerma);//thread的名字,买票数,电影院对象
		Thread buyticketThread2 = new BuyTicketThread("单身狗", 1, cinerma);
		Thread askThread = new AskQuestionThread("爆米花",cinerma);
		
		buyticketThread1.start();
		buyticketThread2.start();
		askThread.start();

class BuyTicketThread extends Thread{//买票线程
	
	int num =0;
	Cinerma cinerma;
 	public BuyTicketThread(String name,int num,Cinerma cinerma){
 		this.num = num;
		 this.cinerma = cinerma;
		 this.setName(name);//设置线程名
	 }
	 
        @Override
	public void run() {
		// TODO Auto-generated method stub
		try {
			for (int i = 0; i < 1000; i++) {//买1000张票
				cinerma.sellTicket(num,i);
				
			}
		} catch (InterruptedException e) {
			 // TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

public class AskQuestionThread extends Thread{//咨询线程
    
    Cinerma cinerma ;
    String name;
    public AskQuestionThread(String name,Cinerma cinerma){
        this.name = name;
        this.cinerma = cinerma;
    }
    
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 3; i++) {
            try {
                cinerma.question(i);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    }

}




方案3:notify()和wake()

建立一个场景,一位母亲有三个孩子,需要给他们做饭,一次只能做一个,每个孩子都要不停的吃饭,做饭和吃饭都需要时间,循环往复

首先建立一个厨房对象,这个对象是最主要的,里面有做饭和吃饭两个方法,重点是,这两个方法都要用synchronized修饰

public class Kitchen {
	int food = 0;//剩余的饭
//做饭函数
 public synchronized void cook() throws InterruptedException{//注意这个函数被synchronized给修饰了 
		if(food>0){//如果当前还有饭
			
			wait();//妈妈线程等待,等待孩子线程notify她,函数会停留在这一句不动,直到有notify
                        //如果被notify了,则执行下面的
                        food = food +1;//做饭
			System.out.println("做完饭后一共剩余"+food);
			System.out.println(Thread.currentThread().getName()+":饭做好了");
			notifyAll();//呼叫孩子线程
			
			
		}else{//如果当前没剩饭了
			food = food +1;
			System.out.println(food);
			System.out.println(Thread.currentThread().getName()+":饭做好了");
			notifyAll();//通知孩子线程
			
		}
<pre name="code" class="java">                System.out.println("通知完孩子后剩余"+food);

 }//吃饭函数public synchronized void eat() throws InterruptedException {//在子线程中调用if(food == 0){wait();//孩子线程等待,等妈妈线程唤醒他,此时函数会停留在这一句
//如果这个时候被notify了
 food -=1;//吃饭 System.out.println(Thread.currentThread().getName()+"抢到了");notifyAll();//通知她妈没饭了System.out.println(food);}else{food -=1;//吃饭System.out.println(food);System.out.println(Thread.currentThread().getName()+"抢到了");notifyAll();//通知她妈System.out.println(food);}}}


使用四个线程,包含一个妈妈线程三个孩子线程,不停的调用kitchen里的方法,如下

Kitchen kitchen = new Kitchen();
		Thread motherThread = new Mother(kitchen);
		Thread chilThread1 = new Childrens("大娃", kitchen);
		Thread chilThread2 = new Childrens("二娃", kitchen);
		Thread chilThread3 = new Childrens("三娃", kitchen);
		
		motherThread.start();
		chilThread1.start();
		chilThread2.start();
		chilThread3.start();

//下面是三个线程的定义
public class Childrens extends Thread{
    Kitchen kitchen;
    public Childrens(String name,Kitchen kitchen){
        this.kitchen = kitchen;
        this.setName(name);
        
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 3; i++) {
            try {
                kitchen.eat();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName()+"吃饱了");
        
        
    }
}
public class Mother extends Thread{
    Kitchen kitchen;
    
    public Mother(Kitchen kitchen){
        this.kitchen = kitchen;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (true) {
            
        
        try {
            kitchen.cook();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        }

    }

}



版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

Linux线程同步的三种控制方法

Linux线程同步的三种控制方法 l         互斥体Mutex l         信号灯S...

Linux 线程同步的三种方法

转自:http://blog.csdn.net/zsf8701/article/details/7844316 线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点。Linux...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

2017·0512_ Linux 线程同步的三种方法

2017·0512_ Linux 线程同步的三种方法

synchronized 线程同步的三种方法

通过一个简单的例子来了解synchronized:使用五个线程,使共享变量 num 加1,最后得到结果 num = 5.类count 实现add函数:public static class count...

解决线程同步的三种方法:

**- 引言 当多个线程同时对同一个对象的实例变量进行操作时,会引起线程的同步问题。此时会引起线程不安全,**总结起来是三点因素: 1.多线程 2.同一对象 3.属性(实例变量) 怎么解决这...

Linux 线程同步的三种方法

线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点。linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量和信号量。 一、互斥锁(mutex) 通过锁机制实现线程...

linux线程同步的三种方法

linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量和信号量。1.互斥锁 通过锁机制实现线程间的同步。1.初始化锁。在Linux下,线程的互斥量数据类型是pthread_mutex_...

Linux 线程同步的三种方法

Linux线程同步的三种方法

三种线程同步方式

三种线程同步方式,即
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)