为什么要使用关键字synchronized?
java程序中可以存在多个线程,但是当多个线程操作同一资源时候,可能会导致数据不一致。
区分synchronized方法与synchronized块:
synchronized方法是一种粗粒度的并发控制,某一时刻,只能有一个线程执行该synchronized方法;
synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized块之外的其他代码是可以被多个线程同时访问到的。
线程同步?
所谓线程同步就是若干个线程都需要使用一个synchronized(同步)修饰的方法,即程序中的若干个线程都需要使用一个方法,而这个方法用synchronized给予修饰,那么多个线程调用该方法时候必须遵守同步机制:
当一个线程A使用synchronized方法时,其他线程想使用这个synchronized方法就必须等待,直至先后才能A使用完毕。即对于synchronized修饰的方法,一次只允许一个线程访问,其他线程只能等待。
2.1 首先看看synchronized方法:
public synchronized void saveOrTake(int amount){ // 这里是同步方法
}
public void saveOrTake(int amount){
synchronized(this){ // 这里是同步块
}
}
//完整代码段:
public class Test01Bank {
/**
* @param args
* @author 牧羊的伯格女皇
* 2015-11-07
*/
public static void main(String[] args) {
Bank bank = new Bank();
bank.setMOney( 200 );
Thread accountant = new Thread(bank); // 会计
Thread cashier = new Thread(bank); // 出纳
accountant.setName("会计");
cashier.setName("出纳");
accountant.start();
cashier.start();
}
}
public class Bank implements Runnable {
int money = 200;
public void setMOney(int n ){
money = n;
}
@Override
public void run() {
if(Thread.currentThread().getName().equals("会计")){
saveOrTake(300);
}else if(Thread.currentThread().getName().equals("出纳")){
saveOrTake(150);
}
}
//存取 同步方法
public synchronized void saveOrTake(int amount){
//synchronized(this){ // 同步块
System.out.println( "首先看看账上原始金额为: " + money );
if(Thread.currentThread().getName().equals("会计")){
for(int i=0;i<3;i++){
money += amount/3;
System.out.println(Thread.currentThread().getName() +" 存入 "+amount/3+" 账上有 " +money+" 万,稍歇会再存");
try {
Thread.sleep( 1000 ); // 这时候出纳仍不能使用该方法,因为sleep并没有释放该对象锁。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}else if(Thread.currentThread().getName().equals("出纳")){
for(int i=0;i<3;i++){
money -= amount/3;
System.out.println(Thread.currentThread().getName() +" 取出 "+amount/3+" 账上有 " +money+" 万,稍歇会再取");
try {
Thread.sleep( 1000 ); // 这时候 会计仍不能使用该方法,因为sleep并没有释放该对象锁。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//}
}
}
试观察运行结果:
2.2 synchronized同步块:
synchronized块写法:
synchronized(object){
}
表示线程在执行的时候会将object对象上锁。(注意这个对象可以是任意类的对象,也可以使用this关键字)。
这样就可以自行规定上锁对象。
import java.util.Random;
public class Demo14synchronized {
public static void main(String[] args) {
SellTickOp s = new SellTickOp(30);
Thread t1 = new Thread( s, "张三");
Thread t2 = new Thread( s, "李四");
Thread t3 = new Thread( s, "王五");
t1.start();
t2.start();
t3.start();
}
}
class SellTickOp implements Runnable{
int tickets;
Random r = new Random();
public SellTickOp(int tickets){
this.tickets = tickets;
}
@Override
public void run() {
while(true){
synchronized(this){ // 这里使用的是同步块
if( tickets > 0 ){
try {
Thread.sleep( r.nextInt(800) );
System.out.println( Thread.currentThread().getName() +" 在购买第 " +(tickets--) + " 张票" );
} catch (InterruptedException e) {
e.printStackTrace();
}
} else{
return;
}
}
}
}
}
synchronized关键字更多理解: http://www.cnblogs.com/mengdd/archive/2013/02/16/2913806.html