为什么要使用关键字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
原文:http://my.oschina.net/gently/blog/527530