zoukankan      html  css  js  c++  java
  • 解决线程安全的几种方式

    一、解决线程安全总体可分为两大类:

    1.使用synchronized关键字(可修饰代码块或方法)

    (1)使用synchronized关键字修饰代码块

    public class ThreadDemo {
    	public static void main(String[] args) {
    		ThreadSafe1 thread = new ThreadSafe1();
    		Thread t1 = new Thread(thread);
    		Thread t2 = new Thread(thread);
    		Thread t3 = new Thread(thread);
    		t1.setName("窗口一");
    		t2.setName("窗口二");
    		t3.setName("窗口三");
    		t1.start();
    		t2.start();
    		t3.start();
    	}
    }
    
    class ThreadSafe1 implements Runnable{
    	
    	//定义车票的数量
    	private int ticket = 100;
    	
    	@Override
    	public void run() {		
    		while(true) {
    			synchronized(ThreadSafe1.class) {   //同步监视器为ThreadSafe1.class,它只加载一次,是唯一的,该同步代码块里包含着共享数据的操作
    				if(ticket > 0) {
    					System.out.println(Thread.currentThread().getName()+":"+"出售第"+ticket+"张车票");
    					//车票数量减一
    					ticket--;
    				}else {
    					break;
    				}
    			}
    		}	
    	}	
    }
    

    (2)使用synchronized关键字修饰方法

    public class ThreadDemo {
    	public static void main(String[] args) {
    		ThreadSafe2 thread = new ThreadSafe2();
    		Thread t1 = new Thread(thread);
    		Thread t2 = new Thread(thread);
    		Thread t3 = new Thread(thread);
    		t1.setName("窗口一");
    		t2.setName("窗口二");
    		t3.setName("窗口三");
    		t1.start();
    		t2.start();
    		t3.start();
    	}
    }
    class ThreadSafe2 implements Runnable{
    	
    	//定义车票的数量
    	private int ticket = 100;
    	
    	@Override
    	public void run() {		
    		while(true) {
    			//调用窗口售票方法
    			sale();
    			if(ticket == 0) {
    				break;
    			}
    	    }	
    	}	
    	//实现窗口售票
    	public synchronized void sale() {   //该方法的同步监视器为ThreadSafe2的对象,它是唯一的,这里面也存放着对共享数据的操作
    		if(ticket > 0) {
    			System.out.println(Thread.currentThread().getName()+":"+"出售第"+ticket+"张车票");
    			//车票数量减一
    			ticket--;
    		}
    	}
    }

    2.使用Lock锁方式解决线程安全问题

    public class ThreadDemo {
    	public static void main(String[] args) {
    		ThreadSafe3 thread = new ThreadSafe3();
    		Thread t1 = new Thread(thread);
    		Thread t2 = new Thread(thread);
    		Thread t3 = new Thread(thread);
    		t1.setName("窗口一");
    		t2.setName("窗口二");
    		t3.setName("窗口三");
    		t1.start();
    		t2.start();
    		t3.start();
    	}
    }
    class ThreadSafe3 implements Runnable{
    	
    	//定义车票的数量
        private int ticket = 100;
        private ReentrantLock lock = new ReentrantLock();
    
    	@Override
    	public void run() {
    		while(true) {
    			try {
    				lock.lock();  //对对操作共享数据的代码进行加锁
    				//进行线程休眠,增加其他线程调用的机会
    				try {
    					Thread.sleep(100);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				if(ticket > 0) {
    					System.out.println(Thread.currentThread().getName()+":"+"出售第"+ticket+"张车票");
    					//车票数量减一
    					ticket--;
    				}else {
    					break;
    				}
    			}finally {
    				lock.unlock(); //进行解锁
    			}
    		}		
    	}		
    }

    二、synchronized关键字与Lock锁方式的区别

    (1)两者都可以解决线程安全问题

    (2)synchronized关键字既可以修饰代码块又可以修饰方法;而Lock锁方式只可以修饰代码块

    (3)synchronied关键字修饰的代码块或方法在运行结束后,会自动释放锁;而Lock锁方式需手动为代码块加锁并释放锁

    (4)从性能上,Lock锁方式优于synchronized关键字

  • 相关阅读:
    【转】批处理第三方命令行工具汇总(2014-11-10更新)
    爬虫问题汇总 + 解决
    ocs的沟通平台
    DSCP 与IP 优先级IP优先级
    IPSec协议
    GRE 协议简介
    使用VLC创建组播流
    华为olt ma5680t常用命令详解
    Python统计列表中的重复项出现的次数的方法
    Kafka
  • 原文地址:https://www.cnblogs.com/li666/p/11131277.html
Copyright © 2011-2022 走看看