Java并发编程:synchronized

  • 什么时候会出现线程安全问题

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

  • 如何解决线程安全问题

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

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

    在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

posted @ 2017-03-21 16:02  qq871928901  阅读(154)  评论(0编辑  收藏  举报