2 基本线程同步
2.1使用 synchronized关键字
这一节中,我们将呈现许多秘诀,这个秘诀教会我们如何使用Java语言提供我们的两个基本同步(synchronization)机制:
? 关键字同步;
? 锁接口和它的实现。
如果你知道一个方法不会被超过一个线程调用,不用使用synchronized
关键字。你能够使用synchronized方法来递归调用,仅仅一个线程能够访问对象的同步块代码(代码块或者方法)。通常情况下,你将使用这个关键字去引用那个能够执行这个方法的指定对象。
当你使用synchrozied关键字去保护一个代码块时,你使用一个对象作为参数。Java虚拟机保证了仅仅一个线程能够访问这个对象保护的代码块(注意到,我们讨论时对象,不是类)。这个比使用synchronized修饰一个一个方法效率高很多。
下面,我们将看一个简单的例子。
定义一个IPad类,实现基本销售业务。
public class IPad {
private longipad1Number;
private longipad2Number;
public IPad(){
ipad1Number = 200;
ipad2Number = 200;
}
public longgetIpad1Number(){
return ipad1Number;
}
public longgetIpad2Number(){
return ipad2Number;
}
/**
* Sells the ipad 1 with the specifiednumber
* @param number
* @return
*/
public synchronizedbooleansellIpad1(intnumber){
if(number <= ipad1Number){
ipad1Number -= number;
return true;
}
return false;
}
/**
* Sells the ipad 2 with the specifiednumber
* @param number
* @return
*/
public synchronizedbooleansellIpad2(intnumber){
if(number <= ipad2Number){
ipad2Number -= number;
return true;
}
return false;
}
/**
* Returns the number of ipad 1.
* @param number
* @return true
*/
public synchronizedbooleanreturnIpad2(intnumber){
ipad2Number += number;
return true;
}
/**
* Returns the number of ipad 2.
* @param number
* @return true
*/
public synchronizedbooleanreturnIpad1(intnumber){
ipad1Number += number;
return true;
}
}
定义IPadShop1类,销售IPad1和IPad2
public class IPadShop1 implements Runnable {
private IPad ipad;
public IPadShop1(IPad ipad){
this.ipad = ipad;
}
/**
* Core method of this IPad office shop 1.Simulates selling and returning ipad number
*/
@Override
public voidrun() {
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(15));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(196));//false
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(19));
System.out.println("Selling ipad1 15 number is "+ipad.returnIpad1(1));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(150));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(96));//false
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(3));
System.out.println("Selling ipad1 15 number is "+ipad.returnIpad2(3));
}
}
定义IPadShop1类,销售IPad1和IPad2。
public class IPadShop2 implements Runnable {
private IPad ipad;
public IPadShop2(IPad ipad){
this.ipad = ipad;
}
/**
* Core method of this IPad office shop 2.Simulates selling and returning ipad number
*/
@Override
public voidrun() {
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(23));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(16));//false
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad1(19));
System.out.println("Selling ipad1 15 number is "+ipad.returnIpad1(1));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(50));
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(96));//false
System.out.println("Selling ipad1 15 number is "+ipad.sellIpad2(13));
System.out.println("Selling ipad1 15 number is "+ipad.returnIpad2(3));
}
}
定义测试类SellingIPad类,实现如下:
public class SellingIPad {
/**
* @param args
*/
public staticvoidmain(String[] args) {
IPad ipad = new IPad();
IPadShop1 shop1 = new IPadShop1(ipad);
Thread t1 = new Thread(shop1, "office shop 1");
IPadShop2 shop2 = new IPadShop2(ipad);
Thread t2 = new Thread(shop2, "office shop 2");
t1.start();
t2.start();
try {
// Waits for the finalization of the threads
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" The number of ipad 1 is : "+ ipad.getIpad1Number());
System.out.println(" The number of ipad 2 is : "+ ipad.getIpad2Number());
}
}
运行结果(注意,每次运行的结果可能不同):
Sellingipad1 15 number is true
Sellingipad1 15 number is true
Sellingipad1 15 number is true
Sellingipad1 15 number is false
Sellingipad1 15 number is true
Sellingipad1 15 number is true
Sellingipad1 15 number is true
Sellingipad1 15 number is false
Sellingipad1 15 number is true
Sellingipad1 15 number is true
Sellingipad1 15 number is false
Sellingipad1 15 number is false
Sellingipad1 15 number is true
Sellingipad1 15 number is true
Sellingipad1 15 number is true
Sellingipad1 15 number is true
The number of ipad 1 is : 110
Thenumber of ipad 2 is : 40
假如我们要使用synchronized的代码块来实现同步,只需要修改IPad类即可。修改后的IPadS类如下所示:
public class IPadS {
private longipad1Number;
private longipad2Number;
private finalObject ipad1Obj,ipad2Obj;
public IPadS(){
ipad1Number = 200;
ipad2Number = 200;
ipad1Obj = new Object();
ipad2Obj = new Object();
}
public longgetIpad1Number(){
return ipad1Number;
}
public longgetIpad2Number(){
return ipad2Number;
}
/**
* Sells the ipad 1 with the specifiednumber
* @param number
* @return
*/
public boolean sellIpad1(int number){
synchronized(ipad1Obj){
if(number <= ipad1Number){
ipad1Number -= number;
return true;
}
return false;
}
}
/**
* Sells the ipad 2 with the specifiednumber
* @param number
* @return
*/
public boolean sellIpad2(int number){
synchronized(ipad2Obj){
if(number <= ipad2Number){
ipad2Number -= number;
return true;
}
return false;
}
}
/**
* Returns the number of ipad 1.
* @param number
* @return true
*/
public boolean returnIpad2(int number){
synchronized(ipad2Obj){
ipad2Number += number;
return true;
}
}
/**
* Returns the number of ipad 2.
* @param number
* @return true
*/
public boolean returnIpad1(int number){
synchronized(ipad1Obj){
ipad1Number += number;
return true;
}
}
}