Java 即使使用synchronized关键字,线程输出也不一致
我对线程非常陌生。我写了一个代码,并期望我的输出为20000。但事实并非如此。请查找以下代码:Java 即使使用synchronized关键字,线程输出也不一致,java,multithreading,synchronization,thread-safety,Java,Multithreading,Synchronization,Thread Safety,我对线程非常陌生。我写了一个代码,并期望我的输出为20000。但事实并非如此。请查找以下代码: class Runner4 implements Runnable { static int count = 0; public synchronized void increase() { count++; } @Override public void run() { for (int i = 0; i < 100
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);
}
}
类Runner4实现Runnable{
静态整数计数=0;
公共空间增加(){
计数++;
}
@凌驾
公开募捐{
对于(int i=0;i<10000;i++){
增加();
}
}
}
公共类线程4{
公共静态void main(字符串[]args){
线程t1=新线程(新Runner4());
t1.start();
线程t2=新线程(新Runner4());
t2.start();
试一试{
t1.join();
t2.连接();
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
System.out.println(Runner4.count);
}
}
有什么解释吗
谢谢 如果
计数
不是静态的
,那么代码就可以工作
public synchronized void increase() {
// method body
}
相当于
public void increase() {
synchronized(this) {
// method body
}
}
由于
count
是static
,因此t1
和t2
都使用不同的锁访问它,从而导致非确定性行为。要么使Runner4.increase
在公共锁上同步(Runner4.class
或私有静态
锁对象可以正常工作),要么使计数
非静态。您正在代码中的两个不同对象上同步(对应于您创建的两个对象)。因此,共享静态变量没有任何保护,您会得到不可预测的结果。基本上,程序中没有有效的同步。您可以通过简单的修改来修复此问题
更改:
public synchronized void increase(){
count++;
}
致:
请注意,我并不是说这是实现此类同步的最佳方式,但重要的是,如果要修改类级变量,也需要类级同步。您试图实现所需的方式实际上不是最佳方式。 更好的方法是定义一个名为Counter的类,如下所示:
public class Counter
{
int count;
public Counter()
{
count = 0;
}
public synchronized void increase() {
count++;
}
public int getCount()
{
return count;
}
}
该类具有增加计数器并获取计数器的方法。
现在需要做的是让两个调用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();
}
}
}
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();
}
}
}
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());
}