Java并发编程:synchronized

时间:2021-09-09 15:55:59
  • 什么时候会出现线程安全问题

    当多个线程同时访问同一个资源时就有可能出现问题。最终的执行结果和实际上的愿望相违背,或者直接导致程序出错

  • 如何解决线程安全问题

    基本上所有的并发模式在解决线程安全问题时,都采用了“序列号访问临界资源”的方案。即在同一时刻,只能有一个线程能够访问临界资源,也称作同步互斥访问。

    通常来说,在访问临界资源的代码前面加一个锁,当访问结束后释放锁,让其他线程继续访问。

    在java中实现了两张方法来实现同步互斥访问  synchronized和lock

  • synchronized的使用

    互斥锁:能够达到互斥访问的锁。

    如果对临界资源加上互斥锁,当一个线程访问临界资源时,其他线程只能等待。

    在java中每一个对象都一个锁标记(monitor),也被称为监视器。多线程访问时某个对象时,只有线程获取到了该对象的锁,才能继续访问。

    在java中可以直接使用synchronized关键字来标记一段代码或者一个方法。当某个线程调用该对象的synchronized方法或者访问synchronized代码块时,这个线程便获得了该对象的锁,其他线程暂时无法访问这个方法,只有等待这个方法执行完毕或者代码块执行完毕,这个线程才会释放该对象的锁,其他线程才能执行这个方法或者代码块。

    对于synchronized方法或者synchronized代码块,当代码出现异常时,jvm会自动释放当前线程占用的锁,因此不会因为异常导致死锁。

  1. 锁方法
    public class TestThread {
    public static void main(String[] args) {
    final InsertData insertData = new InsertData();

    new Thread() {
    public void run() {
    insertData.insert(Thread.currentThread());
    };
    }.start();


    new Thread() {
    public void run() {
    insertData.insert(Thread.currentThread());
    };
    }.start();
    }
    }
    class InsertData {
    private ArrayList<Integer> arrayList = new ArrayList<Integer>();

    public synchronized void insert(Thread thread){
    for(int i=0;i<5;i++){
    try {
    sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(thread.getName()+"在插入数据"+i);
    arrayList.add(i);
    }

    }
    }

    锁住的对象是 insertData ,当创建多个insertData对象分别执行insert方式时,锁就不生效了

  2. 锁代码块
    public class TestThread {
    public static void main(String[] args) {
    final InsertData insertData = new InsertData();

    new Thread() {
    public void run() {
    insertData.insert(Thread.currentThread());
    };
    }.start();


    new Thread() {
    public void run() {
    insertData.insert(Thread.currentThread());
    };
    }.start();
    }
    }
    class InsertData {
    private ArrayList<Integer> arrayList = new ArrayList<Integer>();

    public void insert(Thread thread){
    synchronized(this){
    for(int i=0;i<5;i++){
    try {
    sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(thread.getName()+"在插入数据"+i);
    arrayList.add(i);
    }
    }
    }
    }

    和方法锁一样

  3. 锁静态方法
    public class TestThread {
    public static void main(String[] args) {
    final InsertData insertData = new InsertData();
    final InsertData insertData2 = new InsertData();

    new Thread() {
    public void run() {
    insertData.insert(Thread.currentThread());
    };
    }.start();


    new Thread() {
    public void run() {
    insertData2.insert(Thread.currentThread());
    };
    }.start();
    }
    }
    class InsertData {
    private static ArrayList<Integer> arrayList = new ArrayList<Integer>();

    public static synchronized void insert(Thread thread){
    for(int i=0;i<5;i++){
    try {
    sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(thread.getName()+"在插入数据"+i);
    arrayList.add(i);
    }

    }
    }

    锁住的类,同一个类的对象都被锁住

  参考:http://www.cnblogs.com/dolphin0520/p/3923737.html