1

以下は、最も高速な技術が必要な、シーケンシャル (シングルスレッド) または同時 (マルチスレッド) のいずれかの方法で共通リソースにアクセスするかなり一般的なシナリオです。

より具体的には (以下のサンプル ソース コードを参照)、クラスは、共通のリソース (オブジェクト)を持つ(または) クラス ( )Managerのいくつかのインスタンスを作成します。クラスは実際にはサブクラス化され、サブクラスの実装に応じて、同じスレッドまたは複数のスレッド (たとえば、 を介して) でハンドラを順次実行するために、そのメソッドがオーバーライドされます。RunnableCallableHandlerStoreManagerexecute()ExecutorService

私の質問は、特にシングルスレッドアクセスの場合、同期が冗長であることを考慮して、各オブジェクトの(または) メソッドStore内で共有オブジェクトへのアクセスを同期する最速の (オーバーヘッドの少ない) 方法は何でしょうか?マルチスレッドのサブクラスの実装もあるからです)。runcall()HandlerManager

たとえば、を呼び出す前後にからのオブジェクトsynchronized (this.store) {this.store.process()}を使用するよりも、ブロックの方が優れているでしょうか? または、ストア アクセスごとに個別のメソッドを内部で使用すると、より高速になりますか? たとえば、 を呼び出す代わりに、次のように実行します。Lockjava.util.concurrentthis.store.process()synchronizedHandlerthis.store.process()

private synchronized void processStore()
{
    this.store.process();
}

以下は、(サンプル) ソース コードです。

public class Manager
{
    public Manager()
    {
        Store store = new Store(); // Resource to be shared
        List<Handler> handlers = createHandlers(store, 10);

        execute(handlers);
    }

    List<Handler> createHandlers(Store store, int count)
    {
        List<Handler> handlers = new ArrayList<Handler>();

        for (int i=0; i<count; i++)
        {
            handlers.add(new Handler(store));
        }

        return handlers;
    }

    void execute(List<Handler> handlers)
    {
        // Run handlers, either sequentially or concurrently 
    }
}

public class Handler implements Runnable // or Callable
{
    Store store; // Shared resource

    public Handler(Store store)
    {
        this.store = store;
    }

    public void run() // Would be call(), if Callable
    {
        // ...
        this.store.process(); // Synchronization needed
        // ...
        this.store.report();  // Synchronization needed
        // ...
        this.store.close();   // Synchronization needed
        // ...
    }       
}

public class Store
{
    void process() {}
    void report()  {}
    void close()   {}
}
4

2 に答える 2

3

一般的に:速度に関してはCAS 同期 < synchronized< 。Lockもちろん、これは競合の程度とオペレーティング システムによって異なります。それぞれを試して、ニーズに合った最速のものを判断することをお勧めします。

Java はまた、ロックの省略を実行て、1 つのスレッドにしか見えないオブジェクトのロックを回避します。

于 2012-07-31T19:16:48.330 に答える
1

私の知る限り、アプリが実行されるか、クラスターモードで実行される場合、同期は機能しません(異なるJVM)ので、ロックが唯一のオプションになります。

共通リソースがキューの場合は、ArrayBlockingQueueを使用できます。そうでない場合は、このリソースの同期アクセスを開始します。

于 2012-11-12T12:50:37.297 に答える