java线程替代同步

java线程替代同步,java,multithreading,concurrency,concurrentmodification,Java,Multithreading,Concurrency,Concurrentmodification,我是并发编程新手,下面的代码使用Java线程时,我遇到了一些问题 状态类(该类跟踪职位可用性): public class Status { private static Map<String, Boolean> positions = new HashMap<>(); static { //Initially all positions are free (so set to true) positions.put("

我是并发编程新手,下面的代码使用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);
    }
}
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();
}
}
尽管我使用了“synchronized”,但我注意到,有时Thread3会在Thread2之前出现问题,您能否帮助我解决此问题并获得以下结果

(1) 始终customerThread1应首先占据位置,然后 然后是customerThread2,然后是customerThread3(等等)

(2) customerThread1释放A的位置后 位置应由customerThread2(而不是 而不是customerThread2和customerThread3等待所有位置 由customerThread1)完成),并在customerThread2完成后立即执行 位置“A”,然后customerThread3应将其拾取,等等

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

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


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

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
            }
       }
}

有几个基本问题

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

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

  • 您正在创建多个
    状态
    实例,以访问由
    静态
    变量引用的相同对象。由于所有线程使用不同的锁,因此这种访问是完全不安全的
  • 您的
    occupyOrClear
    已声明
    synchronized
    ,但您的方法
    isClear
    未声明。因此,即使所有线程都对
    occupyOrClear
    使用相同的锁实例,
    isClear
    的结果仍然不可预测,因为它对映射的访问不安全
  • 您有表单的代码
    if(status.isClear(position)){status.occupyOrClear(position,false);…

    即使这两个方法调用中的每一个都是线程安全的,这个序列仍然是不安全的,因为在这两个调用之间,一切都可能发生,最明显的是,条件(刚刚检查的线程)可能会在线程没有注意到的情况下发生变化。因此,两个或多个线程可以调用
    isClear
    ,接收
    true
    ,然后继续执行
    occupyOrClear

  • 您正在使用
    Thread.sleep


  • 在这里,除了启动几个线程之外,我看不到任何并发编程的尝试。在请陌生人帮助您之前,先阅读一些关于这个主题的介绍性材料如何?您的线程中没有使用相同的
    status
    引用。每个线程都在创建一个新的status对象。Dadiv:status具有静态初始化呃,所以我们是否传递它不是问题。但是,我现在已经更改了它,并将它传递给了所有线程。Marko:我已经尝试了方法的“同步”,但不想尝试,因为它会导致巨大的性能问题。为什么会导致巨大的性能问题?