2017-03-13 5 views
0

私はプロデューサーがArrayListのバッファ内のすべての場所を埋める際たびにプログラムが実行を停止します問題に遭遇しました。しかし、理論的には。コンシューマプロセスがまだget()関数に入る可能性があり、notEmptyセマフォが現在10までのシグナル値を取得する原因となります。したがって、消費者プロセスが信号値をセマフォnotFullに戻した後も、プロデューサプロセスは引き続き機能します。(セマフォ使用)は、Java並行処理プログラムについての奇妙なバグ

しかし、それだけで停止し、私は問題を見つけることができません。ここで

はプログラムです:

import java.util.List; 
import java.util.ArrayList; 
import java.util.Random; 
import java.util.concurrent.Semaphore; 
/** 
* A bounded buffer maintains a fixed number of "slots". Items can be 
* inserted into and removed from the buffer. The buffer has a maximum 
* size. 
*/ 

class BoundedBuffer2 
{ 
    // the maximum size of the bounded buffer 
    final public static int MAXSIZE = 10; 
    Semaphore notEmpty = new Semaphore(0); 
    Semaphore notFull = new Semaphore(MAXSIZE); 
    Semaphore sema = new Semaphore(1); 


    // the buffer 
    volatile List<Integer> buffer; 

    public BoundedBuffer2() 
    { 
    buffer = new ArrayList<Integer>(); 
    } 

    // add an element to the end of the buffer if it is not full 
    public synchronized void put(int input) 
    throws InterruptedException 
    { 
     notFull.acquire(); 
     sema.acquire(); 
     buffer.add(input); 
     sema.release(); 
     notEmpty.release(); 
    } 

    // take an element from the front of the buffer 
    public synchronized int get() 
    throws InterruptedException 
    { 
     notEmpty.acquire(); 
     sema.acquire(); 
     int result = buffer.remove(0); 
     sema.release(); 
     notFull.release(); 
     return result; 
    } 

    public int size() 
    { 
    int result = buffer.size(); 
    return result; 
    } 
} 

/** 
* An instance of the Producer class produces new integers at random 
* intervals, and inserts them into a bounded buffer. 
*/ 

class Producer2 extends Thread 
{ 
    // the buffer in which to insert new integers 
    BoundedBuffer2 buffer; 

    public Producer2(BoundedBuffer2 buffer) 
    { 
    this.buffer = buffer; 
    } 

    public void run() 
    { 
    Random random = new Random(); 

    try { 
     while (true) { 
    Thread.sleep(100); 
    //insert a random integer 

    int next = random.nextInt(); 
    buffer.put(next); 



    System.err.println("b.size() increases to " + buffer.size()); 
     } 
    } 
    catch (InterruptedException e) {} 
    } 
} 

/** 
* An instance of the Consumer class consumes integers from a bounded 
* buffer at random intervals. 
*/ 

class Consumer2 extends Thread 
{ 
    // the buffer in which to insert new integers 
    BoundedBuffer2 buffer; 

    public Consumer2(BoundedBuffer2 buffer) 
    { 
    this.buffer = buffer; 
    } 

    public void run() 
    { 
    Random random = new Random(); 

    try { 
     while (true) { 

    Thread.sleep(200); 
      //get the next integer from the buffer 
    int next = buffer.get(); 

    System.err.println("next = " + next); 
    System.err.println("b.size() reducted to " + buffer.size()); 


     } 
    } 
    catch (InterruptedException e) {} 
    } 
} 

public class UseBuffer2 
{ 
    public static void main(String [] args) 
    { 
    BoundedBuffer2 buffer = new BoundedBuffer2(); 
    Producer2 p = new Producer2(buffer); 
    Consumer2 c = new Consumer2(buffer); 

    p.start(); 
    c.start(); 
    } 
} 

ここでは、コンソールに出力されます。

b.size() increases to 1 
b.size() increases to 2 
next = 400524264 
b.size() reducted to 1 
b.size() increases to 2 
b.size() increases to 3 
next = 241523118 
b.size() reducted to 2 
b.size() increases to 3 
next = -1618289090 
b.size() reducted to 2 
b.size() increases to 3 
b.size() increases to 4 
next = -316455080 
b.size() reducted to 3 
b.size() increases to 4 
b.size() increases to 5 
next = 338682909 
b.size() reducted to 4 
b.size() increases to 5 
b.size() increases to 6 
next = -961276708 
b.size() reducted to 5 
b.size() increases to 6 
b.size() increases to 7 
next = 2056804692 
b.size() reducted to 6 
b.size() increases to 7 
b.size() increases to 8 
next = -301063524 
b.size() reducted to 7 
b.size() increases to 8 
b.size() increases to 9 
next = -148582342 
b.size() reducted to 8 
b.size() increases to 9 
b.size() increases to 10 
next = -2076430410 
b.size() reducted to 9 
b.size() increases to 10 
+0

ありませんか? – HendraWD

+0

セマフォーのいずれかに許可を与えていないため、許可を得ることができず、無期限にブロックすることができません。 –

+0

tl; dr javaが[Conditions](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Condition.html)の場合、セマフォを使用する理由は何ですか? – Fildor

答えて

0

synchronizedキーワードがどのように機能するかを読む:https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

関連部分:

同じオブジェクトの同期メソッドの呼び出しが2インターリーブすることはできません。あるスレッドがオブジェクトの同期 方法を実行しているとき、第一 スレッドまで、同じ対象ブロック(実行を停止)するため メソッドを同期invokeが他のすべてのスレッドは、オブジェクトを用いて行われます。任意のスタックトレースは

+0

ありがとう、今私は物事がプログラムの後ろにいかにあるか知っている。 –

0

あなたput()get()メソッドは同期化されています。したがって、プロデューサがput()メソッドを入力した場合は、notFullセマフォを取得しようとしますが、バッファがいっぱいであり、同期メソッドに入るときに取得したロックを保持して永久にブロックすることはできません。したがって、消費者はget()メソッドに入ることができず、バッファから要素を削除することはできません。

+0

助けてくれてありがとう、私はちょうど最近同期キーワードを学ぶ原因です。 –