`
y806839048
  • 浏览: 1132852 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

生产者与消费者

 
阅读更多
//notify();唤醒将对象锁让给我用的对象所在线程,当然用完了就通知对方收回了
//wait();将本对象所在的线程放置进入等待,同时释放次对象上的同步锁synchronized
//此对象在其他线程中可以用,就是wait别人用完了还给我啊
//此两种方法都是对对方
// synchronized(b){...};的意思是定义一个同步块,使用b作为资源锁。b.wait();//的意思是临时释放锁,并阻塞当前线程,好让其他使用同一把锁的线程有机会执行,在这//里要用同一把锁的就是b线程本身.这个线程在执行到一定地方后用notify()通知wait//的线程,锁已经用完,待notify()所在的同步块运行完之后,wait所在的线程就可以//继续执行.
//而且实际上,我们也只能在同步方法或者同步块里面调用wait()和notify().
//同一个副本在不同的线程里面被用,同步块(加锁的只能在一个线程中用,其他的可以在其他线程中用),有了这个基础之上,为了





1、synchronized关键字的作用域有二种:

1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例(不是同一个对象副本)中的synchronized方法;
2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;

3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;

Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

     一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

     二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

     三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

     四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

     五、以上规则对其它对象锁同样适用.

////即只有实际被锁的那个东西才不会在多线程中同时被用,看当前锁类型的粒度,是这个对象(单例),还是这个类。

可以推断:如果一个类中定义了一个synchronized的static函数A,也定义了一个synchronized 的instance函数B,那么这个类的同一对象Obj

在多线程中分别访问A和B两个方法时,不会构成同步,因为它们的锁都不一样。A方法的锁是Obj这个对象,而B的锁是Obj所属的那个Class。

小结如下:

搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程序。


synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的Java线程同步方能获得该锁,重新进入可执行状态。



/*@author shijin
* 生产者与消费者模型中,要保证以下几点:
* 1 同一时间内只能有一个生产者生产     生产方法加锁sychronized
* 2 同一时间内只能有一个消费者消费     消费方法加锁sychronized
* 3 生产者生产的同时消费者不能消费     生产方法加锁sychronized
* 4 消费者消费的同时生产者不能生产     消费方法加锁sychronized
* 5 共享空间空时消费者不能继续消费     消费前循环判断是否为空,空的话将该线程wait,释放锁允许其他同步方法执行
* 6 共享空间满时生产者不能继续生产     生产前循环判断是否为满,满的话将该线程wait,释放锁允许其他同步方法执行   
*/ 
 
//主类  
class  ProducerConsumer 

    public static void main(String[] args)  
    { 
        StackBasket s = new StackBasket(); 
        Producer p = new Producer(s); 
        Consumer c = new Consumer(s); 
        Thread tp = new Thread(p);  //线程的开始要,放到线程中做依托
        Thread tc = new Thread(c); 
       tp.start(); 
        tc.start(); 
    } 

 
//  
class Mantou 

    private int id; 
     
    Mantou(int id){ 
        this.id = id; 
    } 
 
    public String toString(){ 
        return "Mantou :" + id; 
    } 

 
//共享栈空间  
class StackBasket 

    Mantou sm[] = new Mantou[6]; 
    int index = 0; 
     
    /** 
    * show 生产方法.
    * show 该方法为同步方法,持有方法锁;
    * show 首先循环判断满否,满的话使该线程等待,释放同步方法锁,允许消费;
    * show 当不满时首先唤醒正在等待的消费方法,但是也只能让其进入就绪状态,
    * show 等生产结束释放同步方法锁后消费才能持有该锁进行消费
    * @param m 元素
    * @return 没有返回值 
    */  
 
    public synchronized void push(Mantou m){ 
        try{ 
            while(index == sm.length){ 
                System.out.println("!!!!!!!!!生产满了!!!!!!!!!"); 
                this.wait();  //将当前线程停止,释放这个对象上的锁,不再往下面执行
            } 
            this.notify();//唤醒其他要用此对象的线程,让其他线程获得此对象的锁,包括其他线程调用同一方法,当然也有调用其他不同的方法,符合条件就调用,不符合就等待,释放,让其他线程获取锁执行
        }catch(InterruptedException e){ 
            e.printStackTrace(); 
        }catch(IllegalMonitorStateException e){ 
            e.printStackTrace(); 
        } 
         
        sm[index] = m; 
        index++; 
        System.out.println("生产了:" + m + " 共" + index + "个馒头"); 
    } 
 
    /** 
    * show 消费方法
    * show 该方法为同步方法,持有方法锁
    * show 首先循环判断空否,空的话使该线程等待,释放同步方法锁,允许生产;
    * show 当不空时首先唤醒正在等待的生产方法,但是也只能让其进入就绪状态
    * show 等消费结束释放同步方法锁后生产才能持有该锁进行生产
    * @param b true 表示显示,false 表示隐藏 
    * @return 没有返回值 
    */  
    public synchronized Mantou pop(){ 
        try{ 
            while(index == 0){ 
                System.out.println("!!!!!!!!!消费光了!!!!!!!!!"); 
                this.wait(); 
            } 
            this.notify(); 
       }catch(InterruptedException e){ 
            e.printStackTrace(); 
        }catch(IllegalMonitorStateException e){ 
            e.printStackTrace(); 
        } 
        index--; 
        System.out.println("消费了:---------" + sm[index] + " 共" + index + "个馒头"); 
        return sm[index]; 
    } 

 
class Producer implements Runnable 

    StackBasket ss = new StackBasket(); 
    Producer(StackBasket ss){ 
        this.ss = ss; 
    } 
 
    /** 
    * show 生产进程. 
    */  
    public void run(){ 
        for(int i = 0;i < 20;i++){ 
            Mantou m = new Mantou(i); 
            ss.push(m); 
//          System.out.println("生产了:" + m + " 共" + ss.index
"个馒头");  
//          在上面一行进行测试是不妥的,对index的访问应该在原子操作里,因为可能在push之后此输出之前又消费了,会产生输出混乱  
            try{ 
                Thread.sleep((int)(Math.random()*500)); 
            }catch(InterruptedException e){ 
                e.printStackTrace(); 
           } 
        } 
    } 

 
class Consumer implements Runnable 

    StackBasket ss = new StackBasket(); 
    Consumer(StackBasket ss){ 
        this.ss = ss; 
    } 
 
    /** 
    * show 消费进程.
    */  
    public void run(){ 
        for(int i = 0;i < 20;i++){ 
            Mantou m = ss.pop(); 
//          System.out.println("消费了:---------" + m + " 共" + ss.index + "个馒头");  
//  同上  在上面一行进行测试也是不妥的,对index的访问应该在原子操作里,因为可能在pop之后此输出之前又生产了,会产生输出混乱  
            try{ 
                Thread.sleep((int)(Math.random()*1000)); 
            }catch(InterruptedException e){ 
                e.printStackTrace(); 
            } 
        } 
    } 


//由于本程序,设置了最多20次循环,所以进行20次就自动停止,消费的频率低于生产,所以最后留下的是消费的单独进行。
分享到:
评论

相关推荐

    生产者与消费者实验报告

    生产者与消费者模型主要包括两部分:生产者(Producer)和消费者(Consumer)。其中,生产者负责创建数据并将其放入缓冲区,而消费者则从缓冲区中取出数据进行处理。为了确保数据的正确性以及系统的高效运行,必须在...

    生产者与消费者生产者与消费者

    ### 生产者与消费者模型详解 #### 一、引言 生产者-消费者问题作为操作系统中的经典进程同步问题,自1965年由Edsger Dijkstra首次提出以来,一直是计算机科学领域研究的重要内容之一。它不仅展示了信号量机制的...

    pv操作解决生产者与消费者问题

    此外,pv操作还可以广泛应用于各种生产者消费者问题的解决中,使得系统更为可靠和高效。 pv操作是解决生产者与消费者问题的常用方法之一。通过pv操作,我们可以确保生产者进程和消费者进程之间的同步,避免数据的...

    生产者与消费者实验代码

    ### 生产者与消费者实验代码知识点解析 #### 一、实验背景与目的 生产者-消费者问题是一个经典的多线程同步问题,在计算机科学领域中,主要用于研究如何在多个线程之间进行协调工作的问题。该实验旨在通过编程实现...

    生产者与消费者的实验

    **生产者消费者问题的核心概念:** 1. **共享缓冲区**:这是生产者和消费者共享的关键资源。它是一个有限大小的存储区域,用于暂时存放产品。在本实验中,缓冲区的大小是固定的,因此必须管理好何时添加和取出产品...

    操作系统中生产者与消费者问题实例

    操作系统中的生产者与消费者问题是多线程编程中的一个经典模型,它主要研究的是如何有效地在共享资源之间协调生产者和消费者的行为,以避免数据竞争和死锁等问题。在这个C#编写的实例中,我们将深入探讨这个问题及其...

    进程同步实验——生产者与消费者问题算法实现

    在这个实验“进程同步实验——生产者与消费者问题算法实现”中,我们探讨了一个经典的并发问题:生产者-消费者问题。 生产者-消费者问题是多线程编程中的一种典型应用场景,模拟了实际生产流水线的过程。在这个问题...

    java生产者与消费者实验报告

    ### Java生产者与消费者模型详解 ...实验过程中,使用Eclipse IDE搭建开发环境,通过编写和调试代码,成功实现了三个生产者与三个消费者之间的数据同步交互,验证了生产者-消费者模式的有效性和可行性。

    操作系统课程设计——模拟生产者与消费者(java)

    生产者与消费者进程共享一个大小固定的缓冲区。其中,一个或多个生产者生产数据,并将生产的数据存入缓冲区,并有一个或多个消费者从缓冲区中取数据。 2、 系统设计: 系统的设计必须要体现进程之间的同步关系,...

    操作系统生产者与消费者问题Java简单模拟实现

    总的来说,"操作系统生产者与消费者问题Java简单模拟实现"这个项目提供了一个直观的多线程编程实例,帮助我们理解和实践Java中的线程同步技术,这对于理解和解决实际并发问题具有重要意义。通过分析这个项目,我们...

    操作系统课程设计生产者与消费者

    ### 操作系统课程设计:生产者与消费者问题详解 #### 一、问题背景与意义 在计算机科学领域,特别是操作系统理论中,“生产者-消费者”问题是一个非常经典的进程同步问题。这一问题最早由著名的计算机科学家Edsger...

    操作系统实验之进程的互斥与同步(生产者与消费者问题)VC++

    例如,在生产者与消费者问题中,有一个缓冲区作为共享资源,生产者将产品放入缓冲区,而消费者则从缓冲区取出产品。为了保证数据的一致性,必须确保在任何时候,缓冲区要么只允许一个生产者写入,要么只允许一个消费...

    操作系统实验生产者与消费者实验报告及代码

    根据给定的文件信息,以下是对“操作系统实验生产者与消费者实验报告及代码”的详细解析: ### 一、实验背景与目的 本次实验基于Windows操作系统环境,通过利用其提供的API函数来实现进程间的互斥与同步机制。实验...

    生产者与消费者问题(C++)

    在生产者与消费者问题中,可以使用两个信号量分别控制生产者和消费者对缓冲区的操作。 - **互斥锁**:另一种常见的同步机制,用于确保同一时间只有一个进程能够访问临界资源。在本例中,可以使用互斥锁来防止生产者...

    利用单线程完成的生产者与消费者程序

    然而,给定的标题“利用单线程完成的生产者与消费者程序”表明,这个程序是在单线程环境中实现的,这意味着没有并发线程,而是通过某种机制模拟了生产者和消费者的行为。 生产者-消费者模型通常用于处理数据流,...

    进程同步与互斥 生产者与消费者问题--操作系统大作业

    ### 进程同步与互斥:生产者与消费者问题 #### 一、基础知识与概念解析 **1.1 操作系统的基本概念** 操作系统(Operating System, OS)是计算机系统的核心软件,负责管理和协调计算机硬件资源及软件资源。它通过...

    Java生产者与消费者

    在Java编程中,"生产者与消费者"模式是一种经典的多线程问题,它涉及到了并发处理和资源管理。这个模式的核心思想是通过共享一个有限的缓冲区,使得生产者线程可以将产品放入缓冲区,而消费者线程则可以从缓冲区取出...

    生产者与消费者模式

    在生产者与消费者模式中,生产者模块负责创建数据,消费者模块则负责处理这些数据。两者之间通过一个缓冲区进行交互,这个缓冲区可以是队列、环形缓冲区或双缓冲区等形式。例如,在一个简单的寄信场景中,写信的人...

    操作系统生产者与消费者课程设计报告

    操作系统生产者与消费者课程设计报告

Global site tag (gtag.js) - Google Analytics