如何避免在多线程时访问相同的静态计数器
How to avoid accessing the same static counter while multithreading
我是多线程的新手,有点困惑。我如何使用同步键给出输出: 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();
}
}
您可以使用同步静态方法(在 increment
中,无论如何您只是在静态字段上操作,所以为什么不将其设为静态?)。
public static synchronized void increment() {
x=x+1;
System.out.println(x+" "+ name);
}
这种方法是在整个class对象上同步的。
如果出于某种原因你真的不想让这个方法静态你可以明确地同步class对象
上的关键部分
public void increment() {
synchronized(Test1.class) {
x=x+1;
System.out.println(x+" "+ name);
}
}
我建议使用 AtomicInteger 调用 incrementAndGet()。这将自动增加变量并防止其他线程返回对该变量的调用,直到删除前面的锁,因此您的增量方法将是:
System.out.println(x.incrementAndGet()+" "+ name);
您也可以像其他用户发布的那样使用 synchronized 块,但这两个建议的缺点是您牺牲了对锁对象的控制,因为方法上的 synchronized 关键字等同于:
synchronized (this) { }
并且引用 class 对象不会将对象保留在 class 内部。
我是多线程的新手,有点困惑。我如何使用同步键给出输出: 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();
}
}
您可以使用同步静态方法(在 increment
中,无论如何您只是在静态字段上操作,所以为什么不将其设为静态?)。
public static synchronized void increment() {
x=x+1;
System.out.println(x+" "+ name);
}
这种方法是在整个class对象上同步的。
如果出于某种原因你真的不想让这个方法静态你可以明确地同步class对象
上的关键部分public void increment() {
synchronized(Test1.class) {
x=x+1;
System.out.println(x+" "+ name);
}
}
我建议使用 AtomicInteger 调用 incrementAndGet()。这将自动增加变量并防止其他线程返回对该变量的调用,直到删除前面的锁,因此您的增量方法将是:
System.out.println(x.incrementAndGet()+" "+ name);
您也可以像其他用户发布的那样使用 synchronized 块,但这两个建议的缺点是您牺牲了对锁对象的控制,因为方法上的 synchronized 关键字等同于:
synchronized (this) { }
并且引用 class 对象不会将对象保留在 class 内部。