【问题标题】:Java threads synchronization using token and character printing [duplicate]使用令牌和字符打印的 Java 线程同步 [重复]
【发布时间】:2014-10-24 13:04:35
【问题描述】:

好的,我最近一直在尝试理解线程和线程同步。我编写了一个程序,该程序应该按该顺序一遍又一遍地输出 abc,每个字符都映射到一个线程。问题是,它不工作,我不知道为什么。这是我的代码:

package application2;

public class Application2 {

private static int turn = 0;
private static String[] names = new String[3];

private static class syncThreads extends Thread {

    private final char charToPrint;
    //private final int times;

    public syncThreads(char charToPrint) {
        this.charToPrint = charToPrint;
        //this.times = times;
    }

    @Override
    public synchronized void run() {
        String myName = Thread.currentThread().getName();
        for (int i = 0; i < 20; i++) {
            if (myName.equals(names[turn])) {
                System.out.print(charToPrint);
            }
            turn++;
            if (turn == 3) {
                turn = 0;
            }
        }

        notifyAll();
        try {
            Thread.currentThread().wait(200);
        } catch (InterruptedException e) {

        }
    }

}

public static void main(String args[]) {

    syncThreads t1 = new syncThreads('a');
    names[0] = t1.getName();
    syncThreads t2 = new syncThreads('b');
    names[1] = t2.getName();
    syncThreads t3 = new syncThreads('c');
    names[2] = t3.getName();

    t1.start();
    t2.start();
    t3.start();

    //Join method ensures proper synchronization
    try {
        t1.join();
        t2.join();
        t3.join();
    } catch (Exception e) {
        System.out.println("Interrupt Exception.");
    }

}
}

如您所见,我正在尝试使用同步的 run() 函数,该函数使用令牌值来告诉打印哪个线程。当我运行它时,我得到了非常奇怪的结果,例如 aaaaaabbbbcccc 和 abbabbaaaaccccbbccc 等。知道为什么这些线程没有同步吗?我在这里错过了什么?

感谢您的帮助!

【问题讨论】:

  • 您不仅在错误的事物上同步(这个,而不是共享对象,如 Chris 链接的问题所示),您还在等待中解锁行动。
  • 你在等待循环之外等待。
  • 这完全违背了并发线程的想法——它们异步工作。这很难,因为你正试图用螺丝刀敲钉子。

标签: java multithreading synchronization synchronized


【解决方案1】:

如前所述,试图让各个线程按顺序运行会破坏整个并发性。如果这是您想要的,只需将它们放在一个线程中即可。另一方面,如果您想确保所有三个线程都已运行,然后再让它们重新启动,那么这相当容易:

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Sync {
    private static final CyclicBarrier barrier = new CyclicBarrier(3);

    public static void main(String[] args) {
        new Thread(new CharPrinter('a')).start();
        new Thread(new CharPrinter('b')).start();
        new Thread(new CharPrinter('c')).start();
    }

    public static class CharPrinter implements Runnable {
        private char c;
        private int times = 10;

        public CharPrinter(char c) {
            this.c = c;
        }

        @Override
        public void run() {
            while(times-- > 0) {
                System.out.print(c);
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                } catch (BrokenBarrierException e) {  }
            }
        }
    }
}

这将输出类似“bac/cba/acb/bca/abc/cab/bca/abc/cab/bca”的内容(为清楚起见添加了斜线)。请注意,您始终会在每组三个字符中获得 a、b 和 c 输出,但顺序是不确定的 - 对于并发线程应该是这样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-11
    • 2012-04-28
    • 1970-01-01
    • 2015-07-25
    • 2019-03-01
    • 2014-04-27
    相关资源
    最近更新 更多