Java编程中,经常会遇到同步的使用情况,synchronized是一个极其重要的关键字,属于native方法,这里主要浅谈一下synchronized一些特性:
在synchronized使用中,如果加在非静态方法上是锁定这个方法,即this.void;而在静态方法上,是锁定这个类所有的static方法,即something.void;
下面以代码为例子:
第一个例子:
public class syn {
public static synchronized void test1() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static synchronized void test2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final syn myt2 = new syn();
Thread test1 = new Thread(new Runnable() {
public void run() {
syn.test1();
}
}, "test1");
Thread test2 = new Thread(new Runnable() {
public void run() {
syn.test2();
}
}, "test2");
test1.start();
test2.start();
// TestRunnable tr=new TestRunnable();
// Thread test3=new Thread(tr);
// test3.start();
}
}
猜一猜会发生什么情况?首先,test1和test2会发生竞争,然后确定竞争的对象后再test1的结果输出完毕之后再到test2的结果输出;因为test1方法中synchronized是加在静态方法中的,所以当test1进入线程后会锁住这个类所有的static方法,synchronized加在静态方法中是类锁。
第二个例子:
package syn;
public class syn {
public static synchronized void test1() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public synchronized void test2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final syn myt2 = new syn();
Thread test1 = new Thread(new Runnable() {
public void run() {
syn.test1();
}
}, "test1");
Thread test2 = new Thread(new Runnable() {
public void run() {
myt2.test2();
}
}, "test2");
test1.start();
test2.start();
// TestRunnable tr=new TestRunnable();
// Thread test3=new Thread(tr);
// test3.start();
}
}
猜一猜又会发生什么?没错,此时test1和test2二者不互斥,这个时候到底是test1运行先呢?还是test2运行先呢?这就交给我们计算机了,也就是说,test1和test2都有可能先运行,但是又因为synchronized加在静态方法中仅仅只是锁住了这个类所有的静态方法,所以两者不互斥,test1和test2竞争之后会交替输出。
第三个例子:
package syn;
public class syn {
public synchronized void test1() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public synchronized void test2() {
int i = 5;
while (i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
public static void main(String[] args) {
final syn myt2 = new syn();
Thread test1 = new Thread(new Runnable() {
public void run() {
myt2.test1();
}
}, "test1");
Thread test2 = new Thread(new Runnable() {
public void run() {
myt2.test2();
}
}, "test2");
test1.start();
test2.start();
// TestRunnable tr=new TestRunnable();
// Thread test3=new Thread(tr);
// test3.start();
}
}
这个时候又会发生什么呢?test1和test2共用一个对象,这就好比上厕所的时候,只有一个人出来了,另外一个人才能进去;所以答案很明显了,首先还是test1和test2会发生竞争,决定谁先上厕所,然后test1上了myt2这个厕所之后,才到test2上厕所。
同样的,如果两个同步的静态方法如果公用一个对象,还是一样的结果,而在第二个例子中,如果将test2的方法也改为非静态,结果也是不会变的,因为synchronized关键字在非静态方法上只是对象锁。