同步方法不起作用,但同步块起作用,为啥?
Posted
技术标签:
【中文标题】同步方法不起作用,但同步块起作用,为啥?【英文标题】:Synchronized method does not work but synchronized block does, why?同步方法不起作用,但同步块起作用,为什么? 【发布时间】:2022-01-13 12:53:59 【问题描述】:public class driver
public static void main(String[] args)
PrintNum firstObjectForThread = new PrintNum(0); // the argument is not used, ignore it
firstObjectForThread.startNewThread();
PrintNum secondObjectForThread = new PrintNum(0);
secondObjectForThread.startNewThread();
这是驱动程序调用的类:
public class ClassName implements Runnable
int variableForUpdate;
private Thread t;
private static ArrayList<Integer> intArray;
public ClassName(int variableForUpdate)
super();
this.intArray = new ArrayList<Integer>();
this.variableForUpdate = variableForUpdate;
for (int i = 0; i < 30 ; i++)
this.intArray.add(i);
@Override
public void run()
runThisWhenThreadStarts();
private synchronized void runThisWhenThreadStarts()
System.out.println("Started");
for (int i = 0; i < 30; i++)
System.out.println(intArray.get(i));
public void startNewThread()
t = new Thread(this);
t.start();
如果我使用下面的块同步,输出是同步的:
private void runThisWhenThreadStarts()
synchronized (ClassName.class)
System.out.println("Started");
for (int i = 0; i < 30; i++)
System.out.println(intArray.get(i));
我已经解决这个问题好几个小时了,但无法弄清楚......有人可以解释一下吗? 我还注意到,如果我使用同一个对象调用 startNewThread(),同步将起作用。但我不明白为什么。
PrintNum firstObjectForThread = new PrintNum(0); // the argument is not used, ignore it
firstObjectForThread.startNewThread();
firstObjectForThread.startNewThread();
我想使用来自同一类的两个不同对象,而不是一个对象调用该方法两次(上述解决方法)。
我可以在另一个程序中使用同步方法,有 2 个不同的实例(get 和 put):
public class Hello extends Thread
int x;
Coffee x1;
int threadno;
Hello(int x, Coffee x1)
this.x = x;
threadno = x;
this.x1 = x1;
public void run()
switch (x)
case 0:
System.out.println("Start thread " + threadno + " Get");
break;
case 1:
System.out.println("Start thread " + threadno + " Put");
break;
ops();
System.out.println("Stopping thread " + threadno);
public void ops()
x1.get();
public static void main(String[] args)
Coffee c1 = new Coffee();
Hello get = new Hello(0, c1);
Hello put = new Hello(0, c1);
get.start();
put.start();
Hello 类将调用咖啡类:
class Coffee
boolean available = false; // indicating there nothing to get.
// waiting on each other.
int contents = 55;
public synchronized int get()
System.out.println("Entering Get method " + contents);
for (int i = 0; i < 30; i++)
System.out.println(i);
return contents;
【问题讨论】:
【参考方案1】:在第一个示例中,该方法获取调用该方法的对象实例上的锁。该块不这样做,而是获取类上的锁。
获取实例上的锁对另一个线程没有影响,它是一个不同的对象。两个线程都在获取自己的锁,这是没有用的。两个线程都不会被阻止做任何事情。
获取类上的锁意味着两个线程都试图获取相同的锁。为了使锁定起作用,两个线程必须使用相同的锁定。
在第二个示例中,Coffee 对象由两个线程共享,并且两个线程都试图在 Coffee 对象上获取相同的锁。这意味着获得锁的第二个线程必须阻塞,直到第一个线程释放锁为止,成功锁定会使线程保持在外,直到第一个线程完成。
要了解同步,请跟踪正在获取的锁。
【讨论】:
谢谢。我也是这么想的。但是我有另一个程序实际上可以使用与同一类的 2 个对象进行同步,同步将起作用。你知道为什么吗?我在我的问题中发布了代码。 @IHaveAQuestion:已更新 感谢您的快速回复。为什么两个 Hello 对象共享同一个 Coffee 对象?当 Hello 对象被实例化时,它应该通过“Coffee c1 = new Coffee();”创建一个新的 Coffee 对象?编辑:啊,我明白了!现在一切都说得通了!以上是关于同步方法不起作用,但同步块起作用,为啥?的主要内容,如果未能解决你的问题,请参考以下文章