Thread进阶 (线程锁)

线程锁

为什么需要线程锁?

  • 对于多个线程同时执行一个相同的操作就会对数据进行错误操作、导致线程不安全。
  • 实现等待和唤醒机制。

线程锁的作用

就是当某一个线程拿到这个锁的时候其他线程是无法拿到这把锁,就不会对于数据的操作出现数据偏差。
对于多个线程

锁的实现

实现锁之前必须要有两个条件(1、共享 2、互斥)加锁的对象必定是多个线程共享的,获得锁的对象必定是互斥的,该线程获得锁其他线程不能获得锁的。

  • 在线程里可直接加 synchronized 对方法、对象 、以及代码段进行加锁。
/**
* 线程内部锁机制
**/ 
public class  lockSynchronized{
	 
	 // 首先新建两个线程 对同一常量进行操作
   private int count = 0;
   
   public static void main(String[] args) throws InterruptedException {
   	Thread[]  th2 =new Thread [10];
   	
       for (int i = 0 ; i < 10 ;i++){
           th2[i] = new Thread(new Threadlock());
           th2[i].start();
       }
             Thread.sleep(1000);
   }
	
	//通过多线程访问 同一个count 做++ 最终结果 会小于或者 等于10 如果加上synchronized 
    public  void add(){
       count++;
       System.out.println(1+":"+count);
   }
   
   // 新建一个线程
    class Threadlock extends Thread {
       @Override
       public  void run(){
   // 对于count ++ ;
   	       add();
       }
   }
}


上述代码在没有加锁的情况下会出现数据错乱。 控制台有可能会输出为这样的

1:1
1:2
1:3
1:4
1:5
1:6
1:7
1:8
1:10   // 正常的这里应该是 9 
1:10

现在来实现几种基本加锁的方式,在上面的add()方法;加synchronized

   	// synchronize  是重量级锁 所以直接加在方法上很是消耗性能
    public synchronized void  add(){ 
  		     count++;
     	  System.out.println(1+":"+count);
   }
    	// 通过对象来进行加锁 ,只是这个对象需要是共享 的任意对象都可以。 
    		 public  void  add(){ 
				  synchronized (SyncDemo.class) {
      				  count++;
       				 System.out.println(1+":"+count);
    			}
    }
  • 实现生产者和消费者
    什么叫生产者和消费者 ,比如在餐厅吃饭,你是客户就是消费者,厨师就是生产者。
    1、 厨师在进行生产时 ,消费者需要等待。
    2、 厨师制作食物完成,那么没有新的消费者那么厨师需要等待新的消费。
    3、 所以我们需要一个中间收营员,来提醒厨师和顾客。

/**
* 创建一个收营员的类
**/
public class Cashier{
		 
		 // 定义一个厨师最多能够制作多少份
		 private int MAX_SIZE =10;
		// 定义一个容器 
		 public BlockingQueue<String>  queue= new LinkedBlockingDeque<String>/**
     *  客户点餐
     **/
    public void add(String food){
    		synchronized(Cashier.class){
    		while (true){
    		try{
    		  if(queue.siez()>MAX_SIZE){
    		 	 	this.wait();
    			 }catch (InterruptedException e){
    		 	e.printStackTrace();
			}
			this.notify();
    		queue.offer(food);
		}
	}
	
    /**
     *  客户取餐
     **/
    public void delet(){
    	synchronized(Cashier.class){
    		while (true){
    	 		try{
    			  if(queue.isEmpty()){
    		  		//是空的时候进行等待
    		  		this.wait();
    		 		}catch (InterruptedException e){
    		 		e.printStackTrace();
					}
   		 		String  d =	queue.take();
   		 		this.notify();// 唤醒 点餐
   		 		System.out.print("消费者消费了"+d);
	}

}

 /**
  * 客户线程 消费线程
  **/ 
 public  class Customer extends Thread {
 		// 创建仓库对象 
 		private static  Cashier cashier = new Cashier();
 	
 	public Customer (Cashier cashier){
 		this.cashier = cashier;
 	}
	@Override
	public void run(){
	   // 如果对象不为空
	   if(!cashier.queue.isEmpty()){
	  		 cashier.delet();
	   }
	}
 }
 /**
  * 厨师线程 生产线程
  **/ 
 public  class Cook extends Thread {
 	// 创建仓库对象 
 		private static  Cashier cashier = new Cashier();
 		private String food;
 	public Cook (Cashier cashier,String food){
 		this.cashier = cashier;
 	}
	@Override
	public void run(){
	   // 如果对象为空
	   if(cashier.queue.isEmpty()){
	  		 cashier.add(food);
	   }
	}
 }
	
	public class Test(){
		
		@Test
		public void threadTest(){
				// 中间对象
				Cashier cashier = new Cashier();
				Cook  cook = new Cook (cashier,"aa");
				cook.start();
				Customer customer = new Customer(cashier);
				customer.start();
		}	
}

ReentrantLock 类

在jdk 1.5 中新增加的ReentrantLock 类同样也可以达到这样的效果,并且在功能上有更多的加强,使用上更加的灵活。

package thread.synchronizLock;

import org.junit.Test;
import java.util.concurrent.locks.ReentrantLock;

public  class SyncDemo  {
    // 首先新建两个线程 对同一常量进行操作
    private volatile int count = 0;
	// 创建lock对象
    private ReentrantLock lock = new ReentrantLock();
    @Test
    public  void test() throws InterruptedException {
        Threadlock1  th1 =new Threadlock1 ();

        Thread[]  th2 =new Thread [10];
//        th1.start();

        for (int i = 0 ; i < 10 ;i++){
            th2[i] = new Thread(new Threadlock());
            th2[i].start();
            
            th2[i] = new Thread(new Threadlock1 ());
            th2[i].start();
 
        }
        Thread.sleep(1000);
    }

    public  void add() {
        try {
        	// 加锁
            lock.lock();
            count++;
            System.out.println(1 + ":" + count);
        }finally {
        	// 解锁
            lock.unlock();
        }
    }
     class Threadlock extends Thread {
        @Override
        public  void run(){
           add();
        }
    }

     class Threadlock1 extends Thread {
        @Override
        public void run(){
          for (int i = 0;i < 10 ; i++ ) {
              add();
          }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值