Javaの同期関数

私は次のように同期された関数を持つクラスを持っています:

public synchronized void enqueue(int number) {...}

私のプログラムでは、クラスの特定のオブジェクトに対してこの関数を使いたいスレッドをいくつか実行しています。私がしたいのは、スレッドが単に関数を使ってみることです。それを待たずにロックされていれば、その関数をスキップするだけです。

これは、Java.util.concurencyライブラリを使用し、syncronization primativesのみを使用して できますか?

並行性を使用しないという制限はオプションではありません

0
もし、メソッド呼び出しがオプションでスピードに興味があるのであれば、メソッドをすべて一緒に呼び出すのはスキップします。
追加された 著者 MeBigFatGuy,
いいえ、不可能です。深く掘り下げて、java.util.concurrentオブジェクトを使用する必要があります。
追加された 著者 Maurício Linhares,
@glowcoderどうすれば可能ですか?彼はそこでオブジェクトを使用するか、または同じことを待つ/通知するかのどちらかです。他の選択肢はありますか?
追加された 著者 Maurício Linhares,
なぜこれをもっと簡単にするために作られた構造の代わりにプリミティブだけを使いたいのですか? :-)
追加された 著者 corsiKa,
@マウリシオそれは本当ではない。あなたはそれをすることができますが、解決策はあまりよくありません。
追加された 著者 corsiKa,
@Maurício待機/通知はjava.util.concurrentと同じではありません...
追加された 著者 corsiKa,
@nayishこれが大学のプロジェクトのためのものであれば、それについて先験的に説明しておき、これを宿題としてタグ付けしておくべきです。私はこれが本当の人生仕事のためだと思って、ほぼ完成した実装をしました...
追加された 著者 corsiKa,
これは大学プロジェクトのためのものですが、これは制限の1つです...私もそれについて幸せではありません...
追加された 著者 Nayish,
申し訳ありませんが、私はそれが違いを生み出したのか分かりませんでした...これは余分なクレジットです...誰でも最速のプログラムが勝って、これは間違いなく私が勝つのを助けることができます....
追加された 著者 Nayish,
これはオプションではなく、後で呼び出されますが、すぐに実行することはオプションです...しかし、全てのスレッドは関数を使用して最終的にターンを得るので、飢餓について心配する必要はありません。 ..
追加された 著者 Nayish,

5 答え

私はAtomicIntegerソリューションが好きですが、もちろんAtomicIntegerは並行パッケージの一部です。次の簡単なコードを使用して、同じ原則に従うことができます(効率は低くなります)。

private boolean locked = false;

public void enqueue(int number) {
    synchronized (this) {
        if (locked) {
            return;
        }
        locked = true;
    }

    try {
       //Synchronized goodness goes here.
    } finally {
        synchronized (this) {
            locked = false;
        }
    }
}
3
追加された

YES You can implement locking on your own by managing a static variable in that class, or a using a "lock" text file, for example.

HOWEVER Although this simplistic hack would not be terribly difficult --- the java.util.concurrency package solution would be EVEN EASIER, AND is a better choice because, as you will quickly find, when building multithreaded resources into applications our needs will quickly exceed your current expectations

全同時性パッケージについて心配する必要はありません。AtomicBooleanまたはAtomicLongフィールドを使用する方法を学ぶのに3分かかりますが、最小限の労力で単純なマルチスレッドロジックを有効にするには十分です。

1
追加された
男 - タフな群衆:) ...最初の部分を読んで - 私はそれがapppliesだと思う
追加された 著者 jayunit100,
もう一度..制限は私の考えではありません...私は並行処理パッケージを使用することはできません。そして、この追加がどのくらい多くの仕事が私の教授から与えられたこの恐ろしい制限で、 。
追加された 著者 Nayish,

同期プリミティブを使用するのではなく、 AtomicInteger クラスを使用して、反並行性戦略のCAS(コンペアアンドスワップ)操作を活用します。

public void enqueue(int number) {
    if (!atomicInteger.compareAndSet(0, 1) {
        return;
    }

    try {
       //Synchronized goodness goes here.
    } finally {
        atomicInteger.set(0);
    }
}
0
追加された

あなたがここに制限されているので、ここで私は何をしますか:

あなたがそれをロックすることを教える能力を持つクラスを作ってください。ロックには、パッシブロックとアクティブロックの2種類があります。パッシブロックでは、スレッド数に制限はありません。アクティブなロックはそのスレッドにのみ属します。

パッシブロックが必要な場合は、自分で登録し、完了したら登録を解除する必要があります。すべてのアクティブなロックが完了するまで、内部オブジェクトを待機します。

When you want an active lock, you wait for all current passive locks have unregistered. If there's currently an active lock (store a thread reference to see if there is, utilizing Thread.currentThread()) then wait until notified. You can then set yourself as the referred thread. When you unregister, if there are waiting active locks, notify one of them (consider a Set<thread> to register this). If there aren't, notify all the passive locks that are waiting and they can go through.

ここには未解決の疑問がたくさんあります。私はそれが完璧だとは思わないが、これはあなたが探しているもののほとんどです...

0
追加された

キューを処理するオブジェクトを同期させることができますか?他の誰かがキューを使用している場合、エンキューは何もしません。コンパイルして実行する例があります。非常に単純な例だがきれいではない:

    class Queue {
        public void enqueue(int number) {
           //something in this method for demo purposes only 
            try {
                Thread.sleep(100);
            } catch (InterruptedException e){}
            System.out.println(Thread.currentThread().getName()+" done");
        }
    }

    class Demo {
        private static Queue e = new Queue();

        public void enqueue(int number) {
            Queue q = getQueue();
            if (q!=null) {
                q.enqueue(number);
                releaseQueue(q);
            } else {
               //do nothing since the queue is being used
                System.out.println(Thread.currentThread().getName()+" done doing nothing");
            }
        }

        public synchronized Queue getQueue() {
            Queue b = e;
            e = null;
            return b;
        }

        public synchronized void releaseQueue(Queue q) {
            e = q;
        }

        public static void main(String[] args) {
            for (int j = 0; j < 5; j++) {
                Thread t = new Thread(new Runnable() {
                    public void run() {
                        Demo d = new Demo();
                        d.enqueue(5);
                    }
                }, "Thread "+j);
                t.start();
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e){}
            }
        }

    }
0
追加された