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();
    }
}

那么,如何更改代码以按顺序格式输出1111111111222222222222222222221111111111 ?

4

4 回答 4

6

您正在同步this,即TestProject对象上。由于您有两个单独的对象,因此您有两个单独的锁。因此,无论另一个线程在做什么,两个线程都可以进入该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 默认使用偏向锁定。这意味着锁将有利于最后一个线程访问锁。如果您认为一个线程可以在另一个线程开始之前启动、运行和完成,我希望您在大多数时间另一个线程开始之前让一个线程运行完成。

我刚刚注意到您锁定在循环之外。这将保证您还可以在另一个线程启动之前运行一个线程完成。

这就是您可以强制线程公平交替的方式。

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

注意:如果你想在两个任务之间公平交替,使用一个线程和一个循环要简单得多。

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)。使用连接()

3)。为 Object 类创建一个实例并将其作为参数传递给同步块,像这样Object myObject = TestProject.class现在将 myObject 传递给同步块

使用上述任何一种方式我们都可以实现同步

于 2013-05-22T04:13:28.177 回答