class Call {
int count;
public void increment() {
for (int i = 0; i < 1000; i++)
count++;
}
}
class Caller implements Runnable {
Call c;
public Caller(Call c) {
this.c = c;
}
@Override
public void run() {
// TODO Auto-generated method stub
c.increment();
}
}
class Calling implements Runnable {
Call c;
public Calling(Call c) {
this.c = c;
}
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (c) {
c.increment();
}
}
}
public class SynchronizedBlock {
public static void main(String[] args) throws InterruptedException {
Call call = new Call();
Calling calling = new Calling(call);
Caller caller = new Caller(call);
Thread t1 = new Thread(caller);
Thread t2 = new Thread(calling);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("caller:" + caller.c.count);
}
}
这里已经使增量方法在1个类中同步,而在其他类中我没有使它成为同步的。当我运行上面的代码时,它有时会给出小于2000的计数值。
根据我的理解,由于Calling类的对象已经锁定了对象,因此不需要在Caller类的increment方法中进行同步。
请你帮我理解这里的逻辑。
答案 0 :(得分:1)
由于Calling类的对象已经锁定了对象,所以就在那里 无需在Caller类增量方法中进行同步。
您的理解不正确。为了使变量上的并行操作具有确定性,您必须在每个访问/修改该变量**时进行某种同步。
您还需要synchronize
中的Caller
。
**:这是确保确定性的必要但不充分的条件。
答案 1 :(得分:1)
increment
关键字表示在进入块之前获取锁定并在退出后释放。
由于 t2 获取/释放锁定而 t1 没有,因此实际上没有同步进行。每当分配CPU时间时, t1 就进入块中。
t2 也总是在没有等待的情况下进入块中,因为 t1 永远不会获取锁。
-
如果您同步class Call {
int count;
public synchronized void increment() {
for (int i = 0; i < 1000; i++)
count++;
}
}
方法,您的程序将正常工作:
var cmd = words.Where(c => c.Text == command).First();
完成此更改后,您可以从 t2 中删除同步块。
答案 2 :(得分:0)
当你得到import java.io.*;
public class Nth_Prime
{
public static void main()throws Exception
{
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Which Prime number would you like to find?");
int n = Integer.parseInt(stdin.readLine());
int k = 0;
int counter = 1;
int num=0;
for(int i=3;i<100;i++)
{
k=0;
for(int j=2;j<i;j++)
{
if(i%j!=0)
{
k++;
}
}
if(k!=0)
{
num=i;
counter++;
}
if(counter==n)
{
System.out.println("The number is: "+num);
break;
}
}
}
}
的正确值时,可能发生的事情发生在这些行之间:
2000
这是因为在t1.start();
t2.start();
行执行之前,public void increment();
的执行在一个量子中完成。 Thread Quantum是线程在不同线程可以在处理器核心上运行之前运行的时间。
第一个线程没有锁定对象,偶尔单个量程不会包含t2.start()
的整个执行,这为线程2留出时间开始执行并处理相同的对象数据。这将导致同时存在2个变量increment()
副本,争夺相同的内存。
尝试将增量count
增加到某个数字for (int i = 0; i < 1000; i++)
。您很可能会更频繁地看到应用程序开始失败。