为何要使用关键字synchronized?html
java程序中能够存在多个线程,可是当多个线程操做同一资源时候,可能会致使数据不一致。java
区分synchronized方法与synchronized块:并发
synchronized方法是一种粗粒度的并发控制,某一时刻,只能有一个线程执行该synchronized方法;dom
synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized块以外的其余代码是能够被多个线程同时访问到的。ide
线程同步?this
所谓线程同步就是若干个线程都须要使用一个synchronized(同步)修饰的方法,即程序中的若干个线程都须要使用一个方法,而这个方法用synchronized给予修饰,那么多个线程调用该方法时候必须遵照同步机制:spa
当一个线程A使用synchronized方法时,其余线程想使用这个synchronized方法就必须等待,直至前后才能A使用完毕。即对于synchronized修饰的方法,一次只容许一个线程访问,其余线程只能等待。线程
2.1 首先看看synchronized方法: code
public synchronized void saveOrTake(int amount){ // 这里是同步方法 } public void saveOrTake(int amount){ synchronized(this){ // 这里是同步块 } }
//完整代码段:orm
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