简单实现多线程线程安全(简单易懂)

直接看代码:

背景:模仿多线程抢票

package com.example.institution01.instiServic;

import java.util.ArrayList;
import java.util.List;

public class ThreadTest {
    /**总票数**/
	static int a = 1;

	public static void method() {
		/**抢票t1**/
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				String sell = sell();
				System.out.println(sell);
			}
		});
		/**抢票t2**/
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				String sell = sell();
				System.out.println(sell);
			}
		});

		t1.start();
		t2.start();

	}

	
	
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			method();
		}
	}
	
	
	
	/**出票系统**/
	public static String  sell(){
		a = a - 1;
		if (a >= 0) 
			return Thread.currentThread().getName()+"抢到票===剩余=" + a;
		 else
			return	Thread.currentThread().getName()+"无票";
	}

}

控制台结果:

Thread-0抢到票===剩余=-1
Thread-4无票
Thread-2无票
Thread-3无票
Thread-1无票
Thread-6无票
Thread-5无票
Thread-7无票
Thread-8无票
Thread-10无票
Thread-11无票
Thread-9无票
Thread-14无票
Thread-15无票
Thread-13无票
Thread-12无票
Thread-17无票
Thread-16无票
Thread-18无票
Thread-19无票

可以看到有一个Thread-0抢到票===剩余=-1的线程:

 A线程:a=1        a-1     a=0;

B线程:a=0     a-1     a=-1;

B线程在A线程没有结束的时候改变了a的值,所以A线程输出剩余-1张票;

1.加   synchronized   关键字后:

package com.example.institution01.instiServic;

import java.util.ArrayList;
import java.util.List;

public class ThreadTest {
    /**总票数**/
	static int a = 1;

	public static void method() {
		/**抢票t1**/
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				String sell = sell();
				System.out.println(sell);
			}
		});
		/**抢票t2**/
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				String sell = sell();
				System.out.println(sell);
			}
		});

		t1.start();
		t2.start();

	}

	
	
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			method();
		}
	}
	
	
	
	/**出票系统**/
	public synchronized static String  sell(){
		a = a - 1;
		if (a >= 0) 
			return Thread.currentThread().getName()+"抢到票===剩余=" + a;
		 else
			return	Thread.currentThread().getName()+"无票";
	}

}

控制台:

Thread-1无票
Thread-5无票
Thread-4无票
Thread-3无票
Thread-2无票
Thread-6无票
Thread-0抢到票===剩余=0
Thread-7无票
Thread-10无票
Thread-9无票
Thread-11无票
Thread-8无票
Thread-12无票
Thread-13无票
Thread-15无票
Thread-14无票
Thread-17无票
Thread-16无票
Thread-18无票
Thread-19无票

完美解决这个问题!

2.用LOCK锁解决:

package com.example.institution01.instiServic;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadTest {
	
	private static Lock lock = new ReentrantLock();
	
    /**总票数**/
	static int a = 1;

	public static void method() {
		/**抢票t1**/
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					lock.lock();
					String sell = sell();
					System.out.println(sell);
				} catch (Exception e) {
					e.printStackTrace();
				}finally {
					 lock.unlock();
				}
			}
		});
		/**抢票t2**/
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					lock.lock();
					String sell = sell();
					System.out.println(sell);
				} catch (Exception e) {
					e.printStackTrace();
				}finally {
					 lock.unlock();
				}
			}
		});

		t1.start();
		t2.start();

	}

	
	
	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			method();
		}
	}
	
	
	
	/**出票系统**/
	public static String  sell(){
		a = a - 1;
		if (a >= 0) 
			return Thread.currentThread().getName()+"抢到票===剩余=" + a;
		 else
			return	Thread.currentThread().getName()+"无票";
	}

}

synchronized和Lock 的异同:

同:两者都是解决线程安全问题

异:

  • synchronized关键字定义的不管是同步代码块还是同步方法在执行完成之后都是自动的释放同步监视器(这是一种隐式锁,出了作用域隐式锁将自动的释放)
  • lock需要手动的上锁启动同步和手动解锁结束同步;
  • Lock只有代码块锁,没办法对某一方法上锁
  • Lock锁比较灵活,JVM只需要花费较小的代价来实现线程的调度,性能更好并且有更好的扩展性;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值