[英]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) 解决方案应避免所有竞争条件
有几个基本问题。
您已经破坏了代码并且已经注意到它不起作用。 但是,您不是询问如何修复损坏的代码,而是要求具有更高性能的替代方案。 您将永远无法以这种态度编写工作程序。
显然,您不知道synchronized
是做什么的。 它获取只能由一个线程持有的特定对象实例的锁。 因此,所有在同一对象上同步的代码片段都被强制按顺序执行,并具有必要的内存可见性。 所以你的代码失败有两个原因:
Status
实例,访问static
变量引用的相同对象。 由于所有线程使用不同的锁,这种访问是完全不安全的。occupyOrClear
被声明为synchronized
,但你的方法isClear
不是。 因此,即使所有的线程使用了相同的锁实例occupyOrClear
,结果isClear
因为它不安全的访问地图仍然是不可预知的。 你有表格的代码if(status.isClear(position)) { status.occupyOrClear(position, false); …
与check-then-act反模式相匹配。 即使这两个方法调用中的每一个都是线程安全的,这个顺序仍然是不安全的,因为在这两个调用之间,一切都可能发生,最值得注意的是,线程刚刚检查的条件可能会在线程不注意的情况下发生变化。 因此,两个或更多线程可以调用isClear
,接收true
,然后继续执行occupyOrClear
。
您正在使用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.