线程安全

线程安全

  • 线程安全
    • 线程同步
      • 同步代码块
      • 同步方法
      • 线程状态
      • sleep方法的几个注意点

线程安全

如果多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

线程同步

当我们使用多个线程访问同一资源的时候,且多个线程对资源有写的操作,就容易出现线程安全问题。
要解决上述多线程并发访问一个资源的安全性问题,Java中提供了同步机制synchronized来解决。

有三种方式来完成同步操作:

  1. 同步代码块
  2. 同步方法
  3. 锁机制

同步代码块

同步代码块:synchronized关键字可以用于方法的某个区块中,表示只对这个区块的资源实行互斥访问。
格式:

synchronized(同步锁){

}

同步锁:
对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁

  1. 锁对象可以是任意类型
  2. 多个线程对象要使用同一把锁

注意:在任何时候最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外面等着。

使用同步代码块解决线程安全问题

public class Ticket implements Runnable{
	private int ticket=100;
	Object lock=new Object();
	public void run(){
		while(true){
			synchronized(lock){
				if (ticket>0){
                        try {
                            Thread.sleep(100);
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }
                        String name=Thread.currentThread().getName();
                        System.out.println(name+"正在卖:"+ticket--);
                    }
			}
	}
	}
}

同步方法

同步方法:使用synchronized修饰的方法,就叫作同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着。

public synchronized void method(){
	可能会产生线程安全问题的代码
}

同步锁是谁
对于非静态方法,同步锁就是this
对于静态方法,我们 使用当前方法所在类的字节码对象(类名.class)

线程状态

当线程被创建并启动后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。在线程的生命周期一共有6中状态

New(新建) 线程刚被创建,但是并未启动。还没调用start方法
Runnable(可运行) 线程可以在java虚拟机中运行的状态,可能正在运行自己的代码,也可能没有,这取决于操作系统处理器
Blocked(锁阻塞) 当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态
Waiting(无限等待) 一个线程在等待另一个线程执行一个唤醒动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒
Timed Waiting(计时等待) 同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这个状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep,Object.wait
Teminated(被终止) 因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡

sleep方法的几个注意点

  1. 进入TIMED_WAITING状态的一种常见情形是调用sleep方法,单独的线程也可以调用,不一定非要有协作关系
  2. 为了让其他线程有机会执行,可以将Thread.sleep()的调用放在线程run()之内,这样才能保证该线程执行过程中会睡眠
  3. sleep与锁无关 线程睡眠到期自动苏醒,并返回到Runnable状态

你可能感兴趣的:(JavaSE复习)