java线程同步-这应该是';我不工作,但它是:)-
我在下面举几个例子 我已将java线程同步-这应该是';我不工作,但它是:)-,java,multithreading,thread-safety,threadpool,Java,Multithreading,Thread Safety,Threadpool,我在下面举几个例子 我已将processCommand修改为- private void processCommand() throws InterruptedException { this.command = "xyz"; } 完整代码- import java.util.logging.Level; import java.util.logging.Logger; public class WorkerThread implements Runnable {
processCommand
修改为-
private void processCommand() throws InterruptedException {
this.command = "xyz";
}
完整代码-
import java.util.logging.Level;
import java.util.logging.Logger;
public class WorkerThread implements Runnable {
private String command;
public WorkerThread(String s) {
this.command = s;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(WorkerThread.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(Thread.currentThread().getName() + " Commad at start :" + command);
try {
processCommand();
} catch (InterruptedException ex) {
}
System.out.println(Thread.currentThread().getName() + " Command after processCommand : " + command);
}
private void processCommand() throws InterruptedException {
this.command = "xyz";
}
}
现在,我希望看到同步问题,对吗?基本上,什么时候
System.out.println(Thread.currentThread().getName()+' Start. Command = '+command);
执行时,它可以拾取值xyz
,对吗?但我从来没见过。我在Thread.Sleep中尝试了各种值
那么,是什么使得这个.command=“xyz”在这种情况下,代码>语句是线程安全的吗
我是这样开始的-
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread("" + i);
executor.execute(worker);
}
ExecutorService executor=Executors.newFixedThreadPool(5);
对于(int i=0;i<10;i++){
Runnable worker=新WorkerThread(“+i”);
执行人,执行人(工人);
}
在这里看不到竞争条件的原因是
Runnable worker = new WorkerThread('' + i);
竞争条件涉及共享资源。另一方面,您的所有工作线程都在更改自己的私有成员命令
。要诱导一种竞赛条件,你需要做如下的事情
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread('' + 0);
executor.execute(worker);
worker.setCommand('' + i);
}
for(int i=0;i<10;i++){
Runnable worker=新的WorkerThread(“”+0);
执行人,执行人(工人);
worker.setCommand(“”+i);
}
现在,当工作人员尝试访问命令
字段时,可能会得到过时的0
值或i
值。更新
它仍然不完全是完整程序的样子。。。但根据我的想法,我看不出有任何一点不是线程安全的
有两个点分配命令
,两个点读取值
主线程在构造函数中分配命令
在调用processCommand
之前,第二个线程在run()
中读取command
第二个线程在processCommand
调用processCommand
后,第二个线程在run()
中读取command
最后三个事件发生在同一个线程上,因此不需要同步。第一个和第二个事件发生在不同的线程上,但此时主线程和工作线程之间应该存在“发生在”关系
- 如果主线程是
start()
第二个线程,那么这将提供“在之前发生”的功能。(联合联络小组如是说。)
- 但实际上,我们正在使用
ThreadPoolExecutor.execute(Runnable)
进行移交,并且根据forExecutor
:
内存一致性影响:在将可运行对象提交给执行器之前,线程中的操作发生在其执行开始之前,可能发生在另一个线程中
总之,所有4个感兴趣的事件都已正确同步,并且没有涉及命令的竞争条件
然而,即使这不是线程安全的,您也很难证明这种非线程安全的行为
- 您无法演示它的主要原因是,实际的不安全性是由Java内存模型造成的。只有在存在同步点或建立“之前发生”的东西时,才需要将对
命令的更改刷新到主存。但无论如何,它们都可以被冲掉。。。他们通常是。。。特别是当有足够长的时间间隔,或者系统调用导致上下文切换时。在这种情况下,两者都有
- 第二个原因是
System.err
和System.out
对象是内部同步的,如果您不注意调用它们的方式,可以消除您试图演示的线程安全问题
这就是线程安全问题的“关键”,涉及对共享变量的非同步访问。实际的比赛条件通常涉及非常小的时间窗口;i、 e.需要在几个时钟周期内发生的两个事件(当然不到一微秒)才能引起注意。这很可能很少发生,这就是为什么涉及竞争条件的问题通常很难重现的原因。向我们展示您的完整代码。是什么让您认为这是线程安全的?您的代码在命令
变量上没有同步,并且如果多个线程正在访问命令
,它也不能保证该命令的值。仅仅因为你的代码没有抛出错误,并不意味着它是正确的或安全的:)@greedyfoddha-没错-我不认为它是线程安全的,但我的实验表明它是。在本例中,我如何诱导竞争条件?@user375868启动多个线程,并尝试修改命令@tarrsalah,我已经在这样做了。@assylias是的,即使是静态也会诱导竞争条件。多线程代码的编写非常简单!:)不,static
没有帮助,因为字段没有可识别的正确值。使用static
只能表明,撇开可见性问题不谈,线程交错发生在主线程和辅助线程之间。@TimBender代码很好。OP实际上是在测试一个发布的示例,但替换了问题中发布的流程命令。很可能,这就是为什么很难理解它是如何为您引入竞争条件的。为了声明存在并发错误,您需要某种方法来解释字段的值应该是什么。在您发布的示例代码中,这是不可能的,因为您在紧循环中修改相同的状态,同时让其他线程排队执行睡眠一秒钟。现在,您可以合理地认为该值应该始终为9
,因为循环可能在CPU交换到另一个线程之前完成。然而,这并不能保证。一个合理的结果可能是CPU只在时间片结束之前运行迭代0-4