繁体   English   中英

java线程替代同步

[英]java threads alternative to synchronization

我是并发编程的新手,我在使用 Java 线程的以下代码中遇到了一些问题。

状态类(此类跟踪位置可用性):

public class Status {

    private static Map<String, Boolean> positions = new HashMap<>();

    static {
        //Initially all positions are free (so set to true)
        positions.put("A", true);
        positions.put("B", true);
    }

    public synchronized void occupyOrClear(String position, 
                                    boolean status) {
         positions.put(position, status);
   }

    public boolean isClear(String position) {
        return positions.get(position);
    }
}

MyThread 类:

public class MyThread implements Runnable {

    private String[] positions;

    private String customer;

    public MyThread(String customer, String[] positions) {
        this.positions = positions;
        this.customer = customer;
    }

    private Status status = new Status();

    public void run() {
        for (int i = 0; i < positions.length;) {
            String position = positions[i];
            if (status.isClear(position)) {
                // position occupied now
                status.occupyOrClear(position, false);
                System.out.println(position + " occupied by :"+customer);

                try {
                    //my real application logic goes below (instead of sleep)
                    Thread.sleep(2000);
                } catch (InterruptedException inteExe) {
                    System.out.println(" Thread interrupted ");
                }

                // Now clear the position
                status.occupyOrClear(position, true);
                System.out.println(position + " finished & cleared by:"+customer);
                i++;
            } else {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException inteExe) {
                    System.out.println(" Thread interrupted ");
                }
            }
        }
    }
}

线程测试类:

public class ThreadTest {
    public static void main(String[] args) {
    String[] positions = { "A", "B"};
    Status status = new Status();
    Thread customerThread1 = new Thread(new MyThread(status, "customer1", positions));
    Thread customerThread2 = new Thread(new MyThread(status, "customer2", positions));
    Thread customerThread3 = new Thread(new MyThread(status, "customer3", positions));
    customerThread1.start();
    customerThread2.start();
    customerThread3.start();
}
}

即使我使用了“同步”,我也可以注意到有时 Thread3 会在 Thread2 之前启动,您能帮我解决这个问题并获得以下结果吗?

(1) 总是 customerThread1 应该先占位,然后是 customerThread2,然后是 customerThread3(等等......)

(2) 一旦customerThread1释放了A的位置,customerThread2就应该立即拾取该位置(而不是customerThread2和customerThread3等待customerThread1完成所有位置)。并且一旦customerThread2完成位置'A',那么 customerThread3 应该把它捡起来,等等。

(3) 一旦位置(A、B 等)被释放/可用,下一个 customerThread 应该立即拿起它。

(4) 解决方案应避免所有竞争条件

有几个基本问​​题。

  1. 您已经破坏了代码并且已经注意到它不起作用。 但是,您不是询问如何修复损坏的代码,而是要求具有更高性能的替代方案。 您将永远无法以这种态度编写工作程序。

  2. 显然,您不知道synchronized是做什么的。 它获取只能由一个线程持有的特定对象实例的锁。 因此,所有在同一对象上同步的代码片段都被强制按顺序执行,并具有必要的内存可见性。 所以你的代码失败有两个原因:

    1. 您正在创建多个Status实例,访问static变量引用的相同对象。 由于所有线程使用不同的锁,这种访问是完全不安全的。
    2. 你的occupyOrClear被声明为synchronized ,但你的方法isClear不是。 因此,即使所有的线程使用了相同的锁实例occupyOrClear ,结果isClear因为它不安全的访问地图仍然是不可预知的。
  3. 你有表格的代码
    if(status.isClear(position)) { status.occupyOrClear(position, false); …
    check-then-act反模式相匹配。 即使这两个方法调用中的每一个都是线程安全的,这个顺序仍然是不安全的,因为这两个调用之间,一切都可能发生,最值得注意的是,线程刚刚检查的条件可能会在线程不注意的情况下发生变化。 因此,两个或更多线程可以调用isClear ,接收true ,然后继续执行occupyOrClear

  4. 您正在使用Thread.sleep

您可以尝试使用以下伪代码:

main() {
    //some concurrent queues, eg ConcurrentLinkedQueue
    Queue t1Tasks = new Queue("A","B","C");
    Queue t2Tasks = new Queue();
    Queue t3Tasks = new Queue();
    Thread t1 = new PThread(t1Tasks,t2Tasks,"customer1");
    Thread t2 = new PThread(t2Tasks,t3Tasks,"customer2");
    Thread t3 = new PThread(t3Tasks,null,"customer3");
}

PThread {
       Queue q1,q2;
       PThread(Queue q1, Queue q2,...){}
       run() {
            while (item = q1.get()) {
                  //process item
                  q2.put(item); //to be processed by next thread
            }
       }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM