同步是针对对象而言的,下面是错误示例
//class Foo extends Thread {
// private int val;
//
// public Foo(int v) {
// val = v;
// }
//
// public void printVal(int v) {
// synchronized(this)
// {
// while (true)
// System.out.println(v);
// }
//
// }
//
// public void run() {
// printVal(val);
// }
//}
//运行结果是交替输入出1 3 ,因为以上代码看似加了同步锁,其实是对两个不同的对象加的。对同一个对象加锁才能实现同步
类同步不再对个别的类实例同步而是对类进行同步。对于类Foo而言,它只有唯一的类定义,两个线程在相同的锁上同步,因此只有一个线程可以执行printVal方法。
//class Foo extends Thread {
// private int val;
//
// public Foo(int v) {
// val = v;
// }
//
// public void printVal(int v) {
// synchronized (Foo.class) {
// while (true)
// System.out.println(v);
// }
// }
//
// public void run() {
// printVal(val);
// }
//}
// 这个代码也可以通过对公共对象加锁。例如给Foo添加一个静态成员。两个方法都可以同步这个对象而达到线程安全。
class Foo extends Thread {
private int val;
private static Object lock=new Object();
public Foo(int v) {
val = v;
}
public void printVal(int v) {
synchronized (lock) {
while (true)
System.out.println(v);
}
}
public void run() {
printVal(val);
}
}
上面这个代码需要进行一些额外的说明,因为JVM有一种优化机制,因为String类型的对象是不可变的,因此当你使用""的形式引用字符串时,如果JVM发现内存已经有一个这样的对象,那么它就使用那个对象而不再生成一个新的String对象,这样是为了减小内存的使用。
//class Foo extends Thread {
// private String name;
// private String val;
//
// public Foo(String name, String v) {
// this.name = name;
// val = v;
// }
//
// public void printVal() {
// synchronized (val) {
// while (true)
// System.out.println(name + val);
// }
// }
//
// public void run() {
// printVal();
// }
//}
//
//public class SyncTest {
// public static void main(String args[]) {
// Foo f1 = new Foo("Foo 1:", "printVal");
// f1.start();
// Foo f2 = new Foo("Foo 2:", "printVal");
// f2.start();
// }
//}
public class SyncTest {
public static void main(String args[]) {
Foo f1 = new Foo(1);
f1.start();
Foo f2 = new Foo(3);
f2.start();
}
}
//class Foo extends Thread {
// private int val;
//
// public Foo(int v) {
// val = v;
// }
//
// public void printVal(int v) {
// synchronized(this)
// {
// while (true)
// System.out.println(v);
// }
//
// }
//
// public void run() {
// printVal(val);
// }
//}
//运行结果是交替输入出1 3 ,因为以上代码看似加了同步锁,其实是对两个不同的对象加的。对同一个对象加锁才能实现同步
类同步不再对个别的类实例同步而是对类进行同步。对于类Foo而言,它只有唯一的类定义,两个线程在相同的锁上同步,因此只有一个线程可以执行printVal方法。
//class Foo extends Thread {
// private int val;
//
// public Foo(int v) {
// val = v;
// }
//
// public void printVal(int v) {
// synchronized (Foo.class) {
// while (true)
// System.out.println(v);
// }
// }
//
// public void run() {
// printVal(val);
// }
//}
// 这个代码也可以通过对公共对象加锁。例如给Foo添加一个静态成员。两个方法都可以同步这个对象而达到线程安全。
class Foo extends Thread {
private int val;
private static Object lock=new Object();
public Foo(int v) {
val = v;
}
public void printVal(int v) {
synchronized (lock) {
while (true)
System.out.println(v);
}
}
public void run() {
printVal(val);
}
}
上面这个代码需要进行一些额外的说明,因为JVM有一种优化机制,因为String类型的对象是不可变的,因此当你使用""的形式引用字符串时,如果JVM发现内存已经有一个这样的对象,那么它就使用那个对象而不再生成一个新的String对象,这样是为了减小内存的使用。
//class Foo extends Thread {
// private String name;
// private String val;
//
// public Foo(String name, String v) {
// this.name = name;
// val = v;
// }
//
// public void printVal() {
// synchronized (val) {
// while (true)
// System.out.println(name + val);
// }
// }
//
// public void run() {
// printVal();
// }
//}
//
//public class SyncTest {
// public static void main(String args[]) {
// Foo f1 = new Foo("Foo 1:", "printVal");
// f1.start();
// Foo f2 = new Foo("Foo 2:", "printVal");
// f2.start();
// }
//}
public class SyncTest {
public static void main(String args[]) {
Foo f1 = new Foo(1);
f1.start();
Foo f2 = new Foo(3);
f2.start();
}
}