学习笔记6:synchronized关键字-->线程同步

  1. 为何要使用关键字synchronized?html

    java程序中能够存在多个线程,可是当多个线程操做同一资源时候,可能会致使数据不一致。java

    区分synchronized方法与synchronized块:并发

    synchronized方法是一种粗粒度的并发控制,某一时刻,只能有一个线程执行该synchronized方法;dom

    synchronized块则是一种细粒度的并发控制,只会将块中的代码同步,位于方法内、synchronized块以外的其余代码是能够被多个线程同时访问到的。ide

  2. 线程同步?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

相关文章
相关标签/搜索