0

コードを実行しようとすると、 のような出力が得られます12221121212121221212。メソッドを として宣言するとsynchronized、他のスレッドが制御を引き継ぐことができなくなります

package com.test;

public class TestProject extends Thread {

    public void run() {
        synchronized (this) {
            for (int i = 0; i < 10; i++) {
                System.out.print(getName());
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestProject myProject = new TestProject();
        TestProject myProject1 = new TestProject();
        myProject.setName("1");
        myProject1.setName("2");
        myProject.start();
        myProacject1.start();
    }
}

では、コードを変更して1111111111222222222または2222222221111111111を順次形式で出力するにはどうすればよいでしょうか。

4

4 に答える 4

6

this、つまりTestProjectオブジェクトで同期しています。2 つの別個のオブジェクトがあるため、2 つの別個のロックがあります。したがって、synchronized他のスレッドが何をしているかに関係なく、両方のスレッドがセクションに入ることができます。

のインスタンス間で同期TestProjectするには、静的ロックが必要です。

public class TestProject extends Thread {

    private static final Object lock = new Object();

    public void run() {
        synchronized (lock) {
            ...
于 2013-05-12T11:09:11.350 に答える
1

Java はデフォルトで偏ったロックを使用します。これは、ロックがロックにアクセスする最後のスレッドを優先することを意味します。一方のスレッドが他方のスレッドが開始する前に開始、実行、および終了できると考える場合、ほとんどの場合、一方のスレッドが他方のスレッドが開始する前に実行が完了すると予想されます。

ループの外でロックしていることに気付きました。これにより、他のスレッドが開始する前に、1 つのスレッドを完了まで実行することが保証されます。

これが、スレッドの公平な交替を強制する方法です。

public class TestProject implements Runnable {
    private final Lock lock;
    public TestProject(Lock lock) {
        this.lock = lock;
    }

    public void run() {
        for (int i = 0; i < 10; i++) {
            lock.lock();
            try {
                System.out.print(Thread.currentThread().getName());
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String... ignored) {
        Lock lock = new ReentrantLock(true);
        new Thread(new TestProject(lock), "1").start();
        new Thread(new TestProject(lock), "2").start();
    }
}

印刷できます

12121212121212121212

注:ロックを不公平にすると、取得できます(trueをfalseに変更します)

11111111112222222222

注: 2 つのタスクを公平に切り替えたい場合は、1 つのスレッドとループを使用する方がはるかに簡単です。

public static void main(String... ignored) {
    for (int i = 0; i < 10; i++) {
        // task 1
        System.out.print("1");
        // task 2
        System.out.print("2");
    }
}
于 2013-05-12T11:12:42.833 に答える
0

myProject1 で join メソッドを使用して、他のスレッドが終了するのを待つこともできます

于 2013-05-12T11:13:55.873 に答える
0

これらは、スレッド間の同期を実現するために使用できる次のメソッドです。

1)。静的グローバル ロックを使用し、そのオブジェクト変数を引数として同期ブロックに渡します。

2)。join() を使用する

3)。Object クラスのインスタンスを作成し、それを引数として同期ブロックにObject myObject = TestProject.class渡します。このように myObject を同期ブロックに渡します。

上記の方法のいずれかを使用して、同期を実現できます

于 2013-05-22T04:13:28.177 に答える