• 多线程并发中的同步


    多线程的同步依靠的是对象锁机制,synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问。参考自http://www.cnblogs.com/phinecos/archive/2010/03/13/1684877.html

    实例说明:1.貌似同步,实际不同步的情况

    package com.thread.code.sync;
    
    /**
     * 不能实现线程同步的例子
     * @author  魅力_小生
     * @version  [版本号, 2016年3月4日]
     */
    public class CannotSync
    {
        public static void main(String[] args)
        {
            CannotSync test = new CannotSync();
            //定义5个线程,希望不打断输出:线程1--1..5;线程2--1..5;...线程5--1..5;
            for (int i = 0; i < 5; i++)
            {
                new Thread(test.new MyThread(),"线程"+i).start();
            }
            //结果发现:打印结果并没有按顺序输出
            /*
             * 原因:在普通方法前面加synchronized,锁住的是当前的this对象,也就是每个个new MyThread()对象;
             *      代码中创建了10个线程,而每个线程都持有this对象的对象锁,这不能实现线程的同步
             */
        }
        
        class MyThread implements Runnable{
            @Override
            //貌似同步,实际不同步(当只有一个线程调用时同步,多线程时不同步)
            public synchronized void run()
            {
                for (int i = 0; i < 10; i++)
                {
                    System.out.println(Thread.currentThread().getName()+"--"+i);
                }
            }
        }
    }

    打印结果:线程1未执行完,线程3打断,接着线程4又打断3,接着线程2又打断4...

    线程1--0
    线程1--1
    线程1--2
    线程1--3
    线程1--4
    线程1--5
    线程3--0
    线程4--0
    线程2--0
    线程2--1
    线程2--2
    线程2--3
    线程2--4
    线程2--5
    线程0--0
    ...

    下面看看能实现同步的几种情况:

    1.同步锁指向同一个对象(外部定义的对象)

    package com.thread.code.sync;
    
    /**
     * 实现线程同步的例子1:同步锁指向同一个对象(外部定义的对象)
     * @author  魅力_小生
     * @version  [版本号, 2016年3月4日]
     */
    public class Sync1
    {
        public static void main(String[] args)
        {
            Sync1 test = new Sync1();
            
            //定义一个共用obj,用于共享资源的锁指向同一个对象,实现同步
            Object obj = new Object();
            //定义5个线程,共同竞争同步代码块,先竞争到的先执行完同步块,中间不会被打断
            for (int i = 0; i < 5; i++)
            {
                new Thread(test.new MyThread(obj),"线程"+i).start();
            }
        }
        
        class MyThread implements Runnable{
            private Object obj;
            public MyThread(Object obj){
                this.obj = obj;
            }
            @Override
            public void run()
            {
                synchronized(obj){
                    for (int i = 0; i < 10; i++)
                    {
                        System.out.println(Thread.currentThread().getName()+"--"+i);
                    }
                    System.out.println("------------");
                }
            }
        }
    }

    2.同步锁指向同一个对象(内部定义静态对象)

    package com.thread.code.sync;
    
    /**
     * 实现线程同步的例子2:同步锁指向同一个对象(内部定义静态对象)
     * @author  魅力_小生
     * @version  [版本号, 2016年3月4日]
     */
    public class Sync2
    {
        public static void main(String[] args)
        {
            //定义5个线程,共同竞争同步代码块,先竞争到的先执行完同步块,中间不会被打断
            for (int i = 0; i < 5; i++)
            {
                new Thread(new MyThread(),"线程"+i).start();
            }
        }
        
        static class MyThread implements Runnable{
            //定义静态对象,用于共享资源的锁指向同一个对象,实现同步
            private static Object obj = new Object();
            @Override
            public void run()
            {
                synchronized(obj){
                    for (int i = 0; i < 10; i++)
                    {
                        System.out.println(Thread.currentThread().getName()+"--"+i);
                    }
                    System.out.println("------------");
                }
            }
        }
    }

    3.使用静态同步方法,而不是普通同步方法

    package com.thread.code.sync;
    
    /**
     * 实现线程同步的例子3:使用静态同步方法,而不是普通同步方法
     * @author  魅力_小生
     * @version  [版本号, 2016年3月4日]
     */
    public class Sync3
    {
        public static void main(String[] args)
        {
            //定义5个线程,希望不打断输出:线程1--1..5;线程2--1..5;...线程5--1..5;
            for (int i = 0; i < 5; i++)
            {
                new Thread(new MyThread(),"线程"+i).start();
            }
        }
        
        static class MyThread implements Runnable{
            @Override
            public void run()
            {
                print();
            }
            /*
             * 静态同步方法:
             *  静态方法是所有类实例对象所共享的,因此线程对象在访问此静态方法时是互斥访问的,从而可以实现线程的同步
             */
            private static synchronized void print()
            {
                for (int i = 0; i < 10; i++)
                {
                    System.out.println(Thread.currentThread().getName()+"--"+i);
                }
                System.out.println("------------");
            }
        }
    }

    上面这些同步情况的打印结果:线程竞争到资源后,未被打断

    线程0--0
    线程0--1
    线程0--2
    线程0--3
    线程0--4
    线程0--5
    线程0--6
    线程0--7
    线程0--8
    线程0--9
    ------------
    线程3--0
    线程3--1
    线程3--2
    线程3--3
    线程3--4
    线程3--5
    线程3--6
    线程3--7
    线程3--8
    线程3--9
    ------------
    线程4--0
    线程4--1
    线程4--2
    线程4--3
    线程4--4
    线程4--5
    线程4--6
    线程4--7
    线程4--8
    线程4--9
    ------------
    线程2--0
    线程2--1
    线程2--2
    线程2--3
    线程2--4
    线程2--5
    线程2--6
    线程2--7
    线程2--8
    线程2--9
    ------------
    线程1--0
    线程1--1
    线程1--2
    线程1--3
    线程1--4
    线程1--5
    线程1--6
    线程1--7
    线程1--8
    线程1--9
    ------------
    逃避不一定躲得过,面对不一定最难过
  • 相关阅读:
    数学(1.费马定理 2.扩展欧几里德算法 3.莫比乌斯反演)
    hdu 3068 最长回文(manacher入门)
    hdu 2594 Simpsons’ Hidden Talents(KMP入门)
    hdu 1671&& poj 3630 (trie 树应用)
    hdu 1251 统计难题(trie树入门)
    poj 2001 Shortest Prefixes(字典树trie 动态分配内存)
    poj 2406 Power Strings(KMP入门,next函数理解)
    hdu 2087剪花布条 (KMP入门 子串出现的次数和子串个数)
    python-操作json
    测试用例-错误推断法
  • 原文地址:https://www.cnblogs.com/yangzhenlong/p/5242309.html
Copyright © 2020-2023  润新知