多线程-线程同步

线程同步

数据安全问题

出现问题的原因

  • 多线程环境
  • 共享数据
  • 多条语句同时操作共享数据
数据安全问题的解决

思路:让程序没有安全问题的环境


同步代码块

可以用同步代码块将操作共享数据的多条语句锁起来

synchronized中文释义:同步

//任意对象
private Object obj = new Object();
synchronized (obj) {
    //操作共享数据的语句
}

通过synchronized加锁后,被锁起来的语句不会同时被多个线程执行,这样就可以解决数据安全问题

注:不能用不同的obj作为‘锁’,那样就是用不同的‘锁’来控制代码块,会不起作用
使用实现Runnable的方式时,由于object与this都指代同一个对象,可直接使用,但使用继承Thread类方式时,不可直接使用object,实例化对象时需用静态对象

同步代码块的优缺点
  • 好处:解决了多线程的数据安全性问题
  • 当线程很多时,每个线程都会去判断同步代码块上面的‘锁’,这是一件很耗费资源的事,无形中会降低程序的运行效率

同步方法

同步方法就是将synchronized关键字加到方法上

  • 格式:

    修饰符 synchronized 返回值类型 方法名(方法参数){ }

同步方法的任意对象(obj)为本类(this)

同步静态方法

synchronized同样也可以加在静态方法上

  • 格式:

    修饰符 static synchronized 返回值类型 方法名(方法参数){ }

和同步方法不同,同步静态方法的任意对象(obj)为当前类的字节码文件(.class)

可通过类名.class的方式访问类的字节码文件


线程安全的类

StringBuffer

  • 线程安全,可变的字符序列
  • 从JDK5开始,被StringBuilder替代,如果不需要线程安全,更推荐使用StringBuilder

Vector

  • 线程安全,该类实现了List接口

  • 从Java2平台v1.2开始该类改进了List接口,是集合体系中的一员。Vector被同步,如果不需要线程安全,更推荐使用ArrayList

Hashtable

  • 线程安全,该类实现了哈希表(键值对)
  • 从Java2平台v1.2开始该类改进了Map接口,是集合体系中的一员。Hashtable被同步,如果不需要线程安全,更推荐使用HashMap
线程安全非线程安全
StringBufferStringBuilder
VectorArrayList
HashtableHashMap
Collections.synchronized

除StringBuffer外,其他两个类我们并不常用到

在使用线程安全的集合时,我们通常使用Collections工具类的synchronized系列方法

public class ThreadDemo {
    public static void main(String[] args) {
        //将ArrayList集合变成线程安全的集合
        List<Object> objects = Collections.synchronizedList(new ArrayList<>());
    }
}

Lock锁

为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

Lock实现提供比synchronized方法和语句更广泛的锁定操作

Lock接口提供了获得锁和释放锁的方法

  • void lock():获得锁
  • void unlock():释放锁

Lock是接口不能够实例化,可以用其实现类ReentrantLock实例化对象

  • ReentrantLock():无参构造方法
public class ThreadDemo {
    public static void main(String[] args) {
    //考虑在声明lock的时候加入static和final关键字
        ReentrantLock lock = new ReentrantLock();
        try{
            lock.lock();
            //这里写被枷锁的代码块
        }finally {
            lock.unlock();
        }
    }
}

为了让unlock方法无论何时都被执行,这里使用try finally来实现


死锁

线程同步机制带来的问题:死锁

死锁不能由程序解开,只能是人为解锁

所以我们在编写代码时应该避免死锁的出现