java基础--同步、Lock类、死锁、如何中断线程

一.同步代码块(同步锁)

synchronized(锁){
    操作功效数据的代码
}

同步代码块规则:
当线程进入代码块时,先看一下有没有锁.
如果有锁,就进入执行代码,进入的同时获得这把锁
执行完毕,出同步代码块,把锁放回去
如果没有锁,在同步代码块前等待

优点:数据安全
坏处:效率会降低

二.同步方法

使用关键字synchronized关键词声明在方法上
作用:同一时间,只有一个线程进入同步方法中执行代码.

//接口实现
class TicketRunnable1 implements Runnable{
	private int ticket = 50;
	@Override
	public void run() {
		while(true) {
			if (sellTickets()) {
				break;
			}
			Thread.yield();
		}
	}
public synchronized boolean sellTickets() {
		if (ticket>0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+ "****" +ticket);
			ticket--;
			//返回值 用作循环判断停止
			return false;
		}else {
			return true;
		}
	}

三.Lock类

方法:使用实现类ReentrantLock创建一个对象,获取锁lock();释放锁unlock();

使用格式:
获取锁
try{
    操作共享数据的代码
}finally{
    释放锁
}

四.死锁

死锁是如何产生的:
线程t1先获取锁A,在同步锁的嵌套里等待锁B,同时线程t2先获取锁B,在同步锁里等待锁A;但是锁A被t1拥有,t1需要获得锁B才能释放锁A,同样锁B只有当t2获得锁A才能释放,故都在等待对方释放,形成了无限循环等待
死锁前提
1.必须要有同步锁的嵌套
2.锁唯一

死锁测试代码

//创建A锁
class LockA{
	//为了唯一
	private LockA() {
	}
	//定义一个常量
	public static final LockA LOCK_A = new LockA();
}
//创建B锁
class LockB{
	//为了唯一
	private LockB() {	
	}
	//定义一个常量
	public static final LockB LOCK_B = new LockB();
}
class DeadlockRunnable implements Runnable{
	//声明一个标记
	private boolean isFlag = true;
	//第一次 先进A锁再进B锁
	//下一次 先进B再进A
	@Override
	public void run() {
		//死循环 为了增加死锁的几率
		while(true) {
			if (isFlag) {
				//A-B
				synchronized (LockA.LOCK_A) {
					System.out.println("我是if的LOCK_A锁");
					synchronized (LockB.LOCK_B) {
						System.out.println("我是if的LOCK_B锁");
					}
				}
			}else {
				//B-A
				synchronized (LockB.LOCK_B) {
					System.out.println("我是else的LOCK_B锁");
					synchronized (LockA.LOCK_A) {
						System.out.println("我是else的LOCK_A锁");
					}
				}
			}
			//修改标记
			isFlag = !isFlag;
		}
	}

五.线程如何停止

stop()方法已经过时,不推荐使用

使用标记法
先声明一个boolean类型的作为标记
public boolean ifFlag = false;
然这个标记成为接口中重写run方法的判断条件
while(!ifFlag) {
}
在主函数中,更该标记来中断线程
waitRunnable.ifFlag =true;

六.interrupt方法

1.调用interrupt方法时,线程中有wait() sleep() 等方法
会抛出 InterruptException异常 并且清除中断状态
2.调用interrupt方法时,没有上述方法,
这时会设置(改变)中断状态的值(true--false)

七.关键字 volatile

作用:用来修饰创建标记,使得子线程中的这个状态信息 可以在主线程及时得到修改

猜你喜欢

转载自blog.csdn.net/hehanhh/article/details/80585737