学习多线程编程的时候,有这么段程序,不管如何输入结果总是不能够锁住变量n,
public class JoinThread extends Thread {
private static int n = 0;
// private static Object obj=new Object();
public void run() {
for (int i = 0; i < 10; i++)
try {
addN();
sleep(3); // 为了使运行结果更随机,延迟3毫秒
} catch (Exception e) {
}
}
private synchronized void addN() {
n++;
}
public void printn() {
System.out.println("n=" + n);
}
public static void main(String[] args) throws Exception {
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++) {
threads[i] = new JoinThread();
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
// if (args.length > 0) {
for (int i = 0; i < threads.length; i++) {
// 100个线程都执行完后继续
threads[i].join();
}
// }
new JoinThread().printn();
}
}
有时候n=1000,有时候n=998甚至会变成993
反复查阅资料才知道是synchronized关键字用法错误。
synchronized关键字的作用域有二种:
1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线 程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的 synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。
所以上面程序中的n变量是属于类范围变量,除了用synchronized static 关键字,不管用什么方法都锁不住。
所以将上面程序修改为
public class JoinThread extends Thread {
private static int n = 0;
// private static Object obj=new Object();
public void run() {
for (int i = 0; i < 10; i++)
try {
addN();
sleep(3); // 为了使运行结果更随机,延迟3毫秒
} catch (Exception e) {
}
}
private synchronized static void addN() {
n++;
}
public void printn() {
System.out.println("n=" + n);
}
public static void main(String[] args) throws Exception {
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++) {
threads[i] = new JoinThread();
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
// if (args.length > 0) {
for (int i = 0; i < threads.length; i++) {
// 100个线程都执行完后继续
threads[i].join();
}
// }
new JoinThread().printn();
}
}
则可以看到n=1000的正确结果,n变量被正确锁住了。