【并发编程】-- volatile、Synchronized关键字使用

31 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第24天,点击查看活动详情

volatile 使用

使用volatile方式如下:

public static volatile boolean isStop;
public static void main(String[] args) throws Exception{
	new Thread(()->{
		while(!isStop){
		//业务逻辑
		}
	}).start();
	Thread.sleep(1000);
	isStop = true;
}

通过volatile关键字保证了isStop变量的可见性,当主线程设置isStop为true时,子线程将会读取到最新值,从而停止线程。

Synchronized关键字使用

synchronized关键字同步方式是通过锁实现。

Synchronized关键字可以修饰静态方法、修饰实例方法、修饰代码块,代码实现如下所示。

public class SynchornizedRun {
    public synchronized static void m1(){
        System.out.println("静态方法");
    }
    public synchronized  void m2(){
        System.out.println("实例方法");
    }
    public void m3(){
        synchronized (this){
            System.out.println("代码块");
        }
    }
}

注意点:

synchornized关键字在静态方法中的使用相当于对class对象上锁,而在方法或者方法内均是对类的对象实例上锁。

Executor接口原理

Executor接口是线程池的最顶层接口,它的源码如下:

public interface Executor{
	void execute(Runnable command);
}

参数只需要传入一个Runnable,然后任务即可被执行。设计层面上设计为单线程执行,即command.run(),也就是每个Runnable对象启动一个线程来执行,即new Thread(command).start()。Executor其实是一个执行器,抽象地一个Runnable任务如何执行。

​ 如果采用开启线程执行command,那么会发生什么问题呢?JVM创建一个线程是非常昂贵的,而且还需要陷入内核上下文切换,如此创建一个线程仅仅是为了执行一个command,未免太过浪费,如果有n个command,基于new Thread(command).start()方式,就会启动n个线程,那么怎样优化它们?

将线程Thread缓存起来,如缓存10个线程来处理这n个任务,但是当n大于10时,可以通过创建队列来保存多余的任务即可。关于这两点问题,所以为什么要用到线程池了,而线程池大概就是一个是保存任务的队列,一个保存线程对象的结构。