java线程替代同步
我是并发编程新手,下面的代码使用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("
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:我已经尝试了方法的“同步”,但不想尝试,因为它会导致巨大的性能问题。为什么会导致巨大的性能问题?