Java线程之间控制占用临界资源(共享资源)用的最多就是synchronized,首先获得资源访问权的线程给资源对象加锁,使用完毕以后再释放对象锁。例如打印机的例子:
public class Printer {
public void printLetters(char c) {
for(int i = 0; i<5; i++) {
System.out.print(c);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println();
}
}
主程序测试:
public class Test3 {
public static void main(String[] args){
final Printer p = new Printer();
new Thread(){
public void run(){
p.printLetters('a');
}
}.start();
new Thread(){
public void run(){
p.printLetters('b');
}
}.start();
}
}
执行结果为:
abbaababab
这样使用毫无疑问,打印的a和b会混杂在一起,因为没有加同步控制,两个线程可以任意使用打印机对象。解决办法就是在Printer类的printLetters方法前面加上synchronized关键字。加上以后某个线程会等待先占用打印机的线程使用完毕释放对象锁以后才能得到打印权。加上synchronized关键字以后的执行结果为:
aaaaa bbbbb
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
好了,比如打印机还有别的功能,看下面的例子:
public class Printer {
synchronized public void printBigFile(){
System.out.println(Thread.currentThread().getName()+"打印大文件....");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "打印大文件结束。。。");
}
// public void anotherFunction() {
// System.out.println("另外的非打印功能");
// }
synchronized public void printLetters(char c) {
for(int i = 0; i<5; i++) {
System.out.print(c);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println();
}
}
主程序测试为:
public class Test3 {
public static void main(String[] args){
final Printer p = new Printer();
new Thread(){
public void run(){
p.printLetters('a');
}
}.start();
new Thread(){
public void run(){
p.printLetters('b');
}
}.start();
////////////////////////////////////////////////////
new Thread(){
public void run(){
p.printBigFile();
}
}.start();
new Thread(){
public void run(){
p.printBigFile();
}
}.start();
// Thread.sleep(2000);
// p.anotherFunction();
}
}
执行结果为:
aaaaa Thread-3打印大文件.... Thread-3打印大文件结束。。。 Thread-2打印大文件.... Thread-2打印大文件结束。。。 bbbbb
可以看到printBigFile和printLetters之间也互斥了(它们也不能同时执行),正如上面所说的synchronized关键字锁住的是对象,而不是某个方法或者代码段。
再看上面两段代码中注释掉的部分,Printer类中注释掉的anotherFunction方法,以及在主函数中调用anotherFunction,因为anotherFunction没有加synchronized修饰,所以大概也能知道执行结果了,它打印的东西会夹在其它打印内容的中间,anotherFunction方法随时可以被任何线程同时执行。