Java 如何避免在多线程处理时访问相同的静态计数器

Java 如何避免在多线程处理时访问相同的静态计数器,java,multithreading,synchronization,Java,Multithreading,Synchronization,我是多线程新手,这有点让人困惑。如何使用synchronize键给出1 a然后2 b的输出?换句话说,我希望第一个线程访问静态变量x,增加它,然后第二个线程开始 public class Test1 extends Thread{ static int x=0; String name; Test1(String n){ name=n;} public void increment() { x=x+1; System.out.pr

我是多线程新手,这有点让人困惑。如何使用synchronize键给出1 a然后2 b的输出?换句话说,我希望第一个线程访问静态变量x,增加它,然后第二个线程开始

public class Test1 extends Thread{
    static int x=0;
    String name;

    Test1(String n){ name=n;}
    public void increment() {
        x=x+1;
        System.out.println(x+" "+ name);
    }

    public void run() {
        this.increment();
    }   
}
public class Main {
    public static void main(String args[]) {
        Test1 a= new Test1("a");
        Test1 b= new Test1("b");
        a.start();
        b.start();
    }
}

您可以使用synchronized static方法(在
increment
中,您只是在静态字段上操作,为什么不将其设置为静态呢?)

这种方法在整个类对象上进行同步

如果出于某种原因确实不想使此方法成为静态的,则可以显式地同步类对象上的关键部分

public void increment() {
    synchronized(Test1.class) {
        x=x+1;
        System.out.println(x+" "+ name);
    }
}

我建议使用AtomicInteger调用incrementAndGet()。这将自动递增变量,并防止其他线程返回对变量的调用,直到前面的锁被移除,因此递增方法将是:

System.out.println(x.incrementAndGet()+" "+ name);
您也可以像其他用户发布一样使用同步块,但这两种建议的缺点是您牺牲了对锁对象的控制,因为方法上的同步关键字相当于:

synchronized (this) { }

引用类对象并不会使对象保持在类的内部。

是希望线程一次运行一个线程,还是线程a先运行实际上很重要?不,我不在乎a是否先运行。我关心的是1和2的输出。实际上我尝试过这个,编译器在大多数时候都给我2-2的输出。谢谢它的工作!但是你能解释一下为什么给出的第一种方法,即同步无效增量不起作用吗?不太确定,但可能是System.out本身?@HusseinJaber第一种方法不是“同步无效增量”,而是“静态同步无效增量”。
static
关键字是这里的重要关键字。
AtomicInteger
是一类非常狭窄的问题的解决方案。OP可能首先应该了解保护数据免受冲突(即互斥)的更一般的方法。
synchronized (this) { }