我对线程很新。我编写了一个代码,并期望我的输出始终为20000。但事实并非如此。请找到以下代码:
class Runner4 implements Runnable {
static int count = 0;
public synchronized void increase() {
count++;
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
increase();
}
}
}
public class threading4 {
public static void main(String[] args) {
Thread t1 = new Thread(new Runner4());
t1.start();
Thread t2 = new Thread(new Runner4());
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Runner4.count);
}
}
有任何解释吗?
谢谢!
答案 0 :(得分:1)
您正在同步代码中的两个不同对象(对应于您创建的两个对象)。因此,没有共享静态变量的保护,并且您得到不可预测的结果。基本上,程序中没有有效的同步。您可以通过简单的修改来解决这个问题。
变化:
public synchronized void increase(){
count++;
}
要:
public void increase(){
synchronized(Runner4.class) {
count++;
}
}
请注意,我并不是说这是完成此类同步的最佳方法 - 但重要的是,如果要修改类级别变量,则还需要类级别同步。
答案 1 :(得分:0)
如果count
不是static
,您的代码就可以使用。
public synchronized void increase() {
// method body
}
相当于
public void increase() {
synchronized(this) {
// method body
}
}
由于count
为static
,t1
和t2
都使用不同的锁访问它,从而导致非确定性行为。要使Runner4.increase
在公共锁定上同步(Runner4.class
或private static
锁定对象就可以正常工作),或使count
非静态。
答案 2 :(得分:0)
你想要达到你想要的方式并不是最好的方法。 更好的方法是定义一个名为Counter的类,如下所示:
public class Counter
{
int count;
public Counter()
{
count = 0;
}
public synchronized void increase() {
count++;
}
public int getCount()
{
return count;
}
}
该课程有增加计数器和获取计数器的方法。 你现在需要做的是让一个Counter对象由两个调用increase()方法的线程共享。所以你的线程类看起来像这样:
class Runner4 extends Thread {
Counter count;
public Runner4(Counter c)
{
count = c;
}
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
count.increase();
}
}
}
请注意,该类接受Counter对象并调用increase方法。该类还扩展了Thread而不是实现Runnable。实际上没有什么区别,刚才你的Runner4可以使用Thread类方法。
从你的主要定义一个Counter对象和两个Runner4线程,然后将Counter对象传递给它们中的每一个:
public static void main(String[] args) {
Counter count = new Counter();
Thread t1 = new Runner4(count);
t1.start();
Thread t2 = new Runner4(count);
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(count.getCount());
}