14

セマフォは 0 未満にできますか? つまり、N=3 のセマフォがあり、「ダウン」を 4 回呼び出すと、N は 0 のままですが、1 つのプロセスがブロックされますか?

逆に言えば、最初に電話をかけた場合、N は 3 より大きくなり得るでしょうか? 私が見ているように、N が 3 よりも大きくなる可能性がある場合、最初に数回呼び出すと、後でできるよりも多くの回数を呼び出すことができるため、クリティカル セクションにより多くのプロセスを配置でき、セマフォによって許可されます。 .

誰かが私のためにそれを少し明確にしてくれれば、私はとても感謝しています.

グレッグ

4

6 に答える 6

20

(Javaタグを指定してjava.util.concurrent.Semaphoreの用語を使用します。これらの詳細の一部は実装固有です。「ダウン」はJavaセマフォのacquire()メソッドであり、「アップ」はrelease().)

はい、最後の呼び出しは、別のスレッドが呼び出されるかスレッドが中断さacquire()れるまでブロックされます。release()

はい、release()何度も呼び出してから、さらにダウンすることができます-少なくともjava.util.concurrent.Semaphore.

セマフォの他の実装には、許可の「最大」数の概念があり、その最大数を超えるリリースの呼び出しは失敗する場合があります。JavaSemaphoreクラスは逆の状況を許容します。この場合、セマフォは負の数の許可で開始することができ、acquire()十分な数の呼び出しが行われるまですべての呼び出しが失敗しrelease()ます。許可の数が負でなくなると、再び負になることはありません。

于 2009-08-03T09:09:48.330 に答える
8

0のときに呼び出すと、機能しないはずです。3のときに呼び出すと機能します。(私はJavaについて考えています)。

もう少し追加させてください。多くの人は、ロックを(バイナリ)セマフォのように考えています(つまり、-N = 1であるため、セマフォの値は0(保持)または1(保持されていない)のいずれかです)。しかし、これは完全には正しくありません。ロックには「所有権」の概念があるため、「再入可能」である可能性があります。つまり、ロックを保持しているスレッドは、lock()を再度呼び出すことができます(事実上、カウントを0から-1に移動します)。これは、スレッドがすでにロックを保持しており、ロックを「再入力」できるためです。ロックは再入可能ではない場合もあります。ロック所有者は、lock()と同じ回数unlock()を呼び出すことが期待されます。

セマフォには所有権の概念がないため、利用可能な限り多くの許可を取得できますが、再入可能にすることはできません。つまり、スレッドが値0に遭遇すると、誰かがセマフォをインクリメントするまで、スレッドをブロックする必要があります。

また、私が見たもの(Java)では、セマフォをNより大きくインクリメントできます。これは、所有権にも関係しています。セマフォには所有権の概念がないため、誰でもより多くの許可を与えることができます。スレッドがロックを保持せずにunlock()を呼び出すときはいつでも、それはエラーです。(Javaでは例外がスローされます)。

この考え方がお役に立てば幸いです。

于 2009-08-03T09:21:27.773 に答える
8

こんにちはグレッグは、次の例を検討してください:

public static void main(String [] args) throws InterruptedException {

        Semaphore available = new Semaphore(1, true);

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());
    }

出力が表示された場合、次のようになります。

Acquire : 0
Released : 1
Released : 2
Released : 3
Released : 4
Acquire : 3
Acquire : 2
Acquire : 1
Acquire : 0

そして待っています。

したがって、基本的に許可はリリースごとに増加し、取得は0まで減少します.0に達すると、同じオブジェクトでリリースが呼び出されるまで待機します:)

于 2012-11-06T02:30:26.673 に答える
2

はい、負の値は、セマフォが解放されるのを待機しているプロセスがあることを意味します。正の値は、セマフォがブロックされる前に何度もacquireを呼び出すことができることを意味します。

このように値を考えることができます。正の数は、利用可能なリソースが非常に多いことを意味します。負の値は、現時点ですべてのリソースが取得されているときに、リソースを必要とする多くのエンティティが存在することを意味します。リソースを取得すると値が減少し、解放すると値が増加します。デクリメント後も値が0より大きい場合はリソースを取得し、そうでない場合はエンティティがキューに入れられます。

ウィキペディアのセマフォの良い説明:http: //en.wikipedia.org/wiki/Semaphore_(programming)

于 2009-08-03T09:17:52.617 に答える
1

N は、限られたリソースをカウントするカウンターと見なしてください。リソースの数を負にすることはできないため、N は >= 0 のままです。使用可能なリソースの数が変わると、最大 N も変更する必要があります。それ以外の場合、最初にデクリメントせずに n をインクリメントするのは良いスタイルだとは思いません。

于 2009-08-03T09:13:47.917 に答える
0

java.util.concurrent.Semaphoreメソッドacquire()とを使用するとrelease()、許可は常に になると思います>=0。for ループ内に 1 つのスレッドのみが存在できるように、スレッドを同期させたいとします。sem がSemaphore初期値 1 の型の場合、これは 2 つ以上のスレッドでは機能しません。

while(true){            

    sem.wait(); // wait is acquire

    for(int i=0; i<=5; i++){

        try {
            Thread.sleep(250);
        }catch (InterruptedException e) {}

        System.out.println("Thread "+ threadname+ " " + i);

             }
    sem.signal(); // signal is release }

ただし、Java から Semaphore クラスを実装し、これを可能にする独自のクラスを作成できます。

package yourpackage;

import java.util.concurrent.Semaphore;

public class SemaphoreLayer {
public Semaphore s=null;
public String name;
private int val;

public SemaphoreLayer(int i){
    s=new Semaphore(i); val=i;
}

public void wait(){
 try {
     val--;
     s.acquire();

  } catch (InterruptedException e) {
    System.out.println("Error signal semaphorelayer");
}}

public void signal(){
    if(val<0){val++;}{
        s.release();
        val++;
    }
}

}

val が負の値になることができるようになりました。ただし、これが完全に安全かどうかはわかりません。1 つのスレッドからシグナルがあり、もう 1 つのスレッドから待機している場合、それらが試みval++て、val--これが悪い可能性があるためです。(この可能性は非常に小さいですが、まだ存在するため、コーディングを行っており、100% エラーが発生しないようにする必要がある場合は、このコードを使用することはお勧めしません) Java とキーワードの同期。

于 2016-11-02T15:46:53.263 に答える