Java解决多线程安全方式:

本文深入探讨了多线程环境下实现线程安全的各种方法,包括synchronized关键字、显式锁Lock的使用及其实现原理,通过具体示例展示了如何避免线程间的竞争条件和死锁,确保数据的一致性和程序的正确运行。

解决多线程安全方式:
sychronized:   jvm维护,隐式锁
1. 同步代码块
2. 同步方法

用例:

package com.denganzhi.pp;


class Web12306Demo implements Runnable{
	  private int num=50;
	  boolean isRunning=true;
		@Override
		public void run() {
			while(isRunning){
				getCard4();
			}
		}
		
		// 线程不安全
		// 3 个线程 可能 同时进入方法
		public  void getCard0() {
			if(num<1) {
				isRunning=false;
				return;
			}
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			/***
			 * 出现问题:
			 * C 抢到了,第0张票
               A 抢到了,第-1张票
			 */
			System.out.println(Thread.currentThread().getName()+" 抢到了,第"+ (num--)+ "张票");
		}
		
		// 线程安全,只有一个线程可以进入方法
		public synchronized void getCard1() {
			if(num<1) {
				isRunning=false;
				return;
			}
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			System.out.println(Thread.currentThread().getName()+" 抢到了,第"+ (num--)+ "张票");
		}
		
		// 线程安全 
		public  void getCard2() {
			// this 同一时刻只能被一个 线程 持有
			synchronized (this) {
				if(num<1) {
					isRunning=false;
					return;
				}
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				System.out.println(Thread.currentThread().getName()+" 抢到了,第"+ (num--)+ "张票");
			}
		}
		// 线程不安全,锁定范围不正确
		
		public  void getCard3() {
			synchronized (this) {
				if(num<1) {
					isRunning=false;
					return;
				}
			}
			// a,b,c 线程可能同时出现在这里
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		System.out.println(Thread.currentThread().getName()+" 抢到了,第"+ (num--)+ "张票");
		}
		
		// 线程不安全
		// 锁定资源不正确 ,基础类型 无法锁定
		public  void getCard4() {
			synchronized ((Integer)num) {
				if(num<1) {
					isRunning=false;
					return;
				}
			}
			// B 抢到了,第0张票
			// C 抢到了,第-1张票
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		System.out.println(Thread.currentThread().getName()+" 抢到了,第"+ (num--)+ "张票");
		}
	}

public class Main2 {
	public static void main(String[] args) {
		Web12306Demo web1236=new Web12306Demo();
		
		new Thread(web1236,"A").start();
		new Thread(web1236,"B").start();
		new Thread(web1236,"C").start();
	}

}

3. A,B线程同时锁住资源,互相不释放

package com.denganzhi.pp;


public class Main3 {
	
	public static void main(String[] args) {
		Object goods=new Object();
		Object money=new Object();
		// 2 个线程 访问同一份 资源
		/**
		 * 死锁 ,2个线程都锁住,同一份资源,互相不释放,
		 * 表现:程序阻塞,无法输出system.out.pintln
		 */
		Test1 test1=new Test1(goods,money);
		Test2 test2=new Test2(goods,money);
		Thread thread1=new Thread(test1);
		thread1.start();
		
		Thread thread2=new Thread(test2);
		thread2.start();
	}

}
class Test1 implements Runnable{
	// 资源,线程中的资源,不是 线程共享资源
//	Object goods=new Object();
//	Object money=new Object();
	
	Object goods;
	Object money;
	

	public Test1(Object goods, Object money) {
		super();
		this.goods = goods;
		this.money = money;
	}
	@Override
	public void run() {
	  while(true) {
		  test();
	  }
	}
	public void test() {
		synchronized(goods) {
		  try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		 synchronized (money) {
		}
	  }
	System.out.println("一手货,一手给钱");
	}
}

class Test2 implements Runnable{
	// 资源,线程中的资源,不是 线程共享资源
//	Object goods=new Object();
//	Object money=new Object();
	
	Object goods=null;
	Object money=null;
	

	public Test2(Object goods, Object money) {
		super();
		this.goods = goods;
		this.money = money;
	}
	@Override
	public void run() {
	  while(true) {
		  test();
	  }
	}
	public void test() {
		synchronized(money) {
		  try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		 synchronized (goods) {
		}
	  }
		System.out.println("一手给钱,一手给货");
	}
}

3. 同步锁Lock jdk1.5以后,  上锁以后必须unlock[在finally]

案例:买票代码

1.1.  问题代码:

package com.denganzhi.pp;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Main2 {

	 public static void main(String[] args) {
		 AtomicDemo auAtomicDemo=new AtomicDemo();
		 Thread thread=null;
		 for (int i = 0; i < 10; i++) {
			 thread=new Thread(auAtomicDemo);
			 thread.setName("线程:"+i );
			 thread.start();
		}
		
	}
}
class AtomicDemo implements Runnable{
	// 还 剩下 10 张票 ,10个人来 抢票
	private int num=10;
	Lock lock=new ReentrantLock();
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	//lock.lock();   // 上锁
		
		try {
			Thread.sleep(50);
			
			int num=getSerialNumber();
			if(num <= 0){
				System.err.println(Thread.currentThread().getName() +" 没有抢到火车票");
			}else{
				System.out.println(Thread.currentThread().getName() +" 抢到第" + num + "张火车票");
			}
		
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//lock.unlock();  //释放锁
		}
		
	
	}
	public int getSerialNumber() {
		return num--;
	}
	
}

运行结果: 一张火车票被多个人抢到,数据错误

线程:7 抢到第10张火车票
线程:8 抢到第7张火车票
线程:4 抢到第9张火车票
线程:3 抢到第9张火车票
线程:5 抢到第10张火车票
线程:0 抢到第8张火车票
线程:2 抢到第8张火车票
线程:1 抢到第8张火车票
线程:9 抢到第10张火车票
线程:6 抢到第10张火车票

3. 同步锁Lock jdk1.5以后,  上锁以后必须unlock[在finally] 

package com.denganzhi.pp;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Main2 {

	 public static void main(String[] args) {
		 AtomicDemo auAtomicDemo=new AtomicDemo();
		 Thread thread=null;
		 for (int i = 0; i < 10; i++) {
			 thread=new Thread(auAtomicDemo);
			 thread.setName("线程:"+i );
			 thread.start();
		}
		
	}
}
class AtomicDemo implements Runnable{
	// 还 剩下 10 张票 ,10个人来 抢票
	private int num=10;
	Lock lock=new ReentrantLock();
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	lock.lock();   // 上锁
		
		try {
			Thread.sleep(50);
			
			int num=getSerialNumber();
			if(num <= 0){
				System.err.println(Thread.currentThread().getName() +" 没有抢到火车票");
			}else{
				System.out.println(Thread.currentThread().getName() +" 抢到第" + num + "张火车票");
			}
		
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			lock.unlock();  //释放锁
		}
		
	
	}
	public int getSerialNumber() {
		return num--;
	}
	
}

 正确输出结果:

线程:0 抢到第10张火车票
线程:1 抢到第9张火车票
线程:2 抢到第8张火车票
线程:3 抢到第7张火车票
线程:4 抢到第6张火车票
线程:5 抢到第5张火车票
线程:6 抢到第4张火车票
线程:7 抢到第3张火车票
线程:8 抢到第2张火车票
线程:9 抢到第1张火车票

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值