美文网首页
多线程之线程同步

多线程之线程同步

作者: vaneL | 来源:发表于2017-08-03 17:40 被阅读0次

    同步的方法:

    1.Java 同步关键字(synchronized)

    • 实例方法
      实例方法同步是同步在拥有该方法的对象上。
    public synchronized void add(int value){
        this.count += value;
     }
    
    • 静态方法
      静态方法的同步是指同步在该方法所在的类对象上。
    public static synchronized void add(int value){
        this.count += value;
     }
    
    • 实例方法中的同步块
      使用了“this”,即为调用add方法的实例本身。在同步构造器中用括号括起来的对象叫做监视器对象。
      同步实例方法使用调用方法本身的实例作为监视器对象。
    public void add(int value){
        synchronized(this){
           this.count += value;
        }
      }
    
    • 静态方法中的同步块
    public static synchronized void log1(String msg1, String msg2){
           log.writeln(msg1);
           log.writeln(msg2);
        }
    public static void log2(String msg1, String msg2){
           synchronized(MyClass.class){
              log.writeln(msg1);
              log.writeln(msg2);
           }
    }
    
    

    synchronized关键字修饰方法的时候,同步锁是this,即等效于代码块synchronized(this) {...}。

    public void output(String name) {
                int len = name.length();
                synchronized (this) {
                    for (int i = 0; i < len; i++) {
                        System.out.print(name.charAt(i));
                    }
                    System.out.println();
                }
            }
    
    public synchronized void output(String name) {
                int len = name.length();
                    for (int i = 0; i < len; i++) {
                        System.out.print(name.charAt(i));
                    }
                    System.out.println();
            }
    

    synchronized关键字修饰static方法的时候,同步锁是该类的字节码对象,即等效于代码块synchronized(classname.class) {...}。

    public static synchronized void output(String name) {
                int len = name.length();
                    for (int i = 0; i < len; i++) {
                        System.out.print(name.charAt(i));
                    }
                    System.out.println();
            }
    
    public void output(String name) {
                int len = name.length();
                synchronized (Outputer.class) {
                    for (int i = 0; i < len; i++) {
                        System.out.print(name.charAt(i));
                    }
                    System.out.println();
                }
            }
    

    同步代码块的锁是任意对象。只要不同的线程都执行同一个同步代码块的时候,这个锁随便设。
    同步函数的锁是固定的this。当需要和同步函数中的逻辑实行同步的时候,代码块中的锁必须为this。
    静态同步函数的锁是该函数所属类的字节码文件对象。该对象可以用this.getClass()方法获取,也可以使用 当前类名.class 表示。

    1. Object的wait与notify
    2. 使用特殊域变量(volatile)实现线程同步
      ● volatile关键字为域变量的访问提供了一种免锁机制
      ● 使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新
      ● 因此每次使用该域就要重新计算,而不是使用寄存器中的值
      ● volatile不会提供任何原子操作,它也不能用来修饰final类型的变量
    3. 使用重入锁实现线程同步
      注:关于Lock对象和synchronized关键字的选择:
      a.最好两个都不用,使用一种java.util.concurrent包提供的机制,能够帮助用户处理所有与锁相关的代码。
      b.如果synchronized关键字能满足用户的需求,就用synchronized,因为它能简化代码
      c.如果需要更高级的功能,就用ReentrantLock类,此时要注意及时释放锁,否则会出现死锁,通常在finally代码释放锁
    public class Counter{
        private int count = 0;
        public int inc(){
            synchronized(this){
                return ++count;
            }
        }
    }
    
    public class Counter{
        private Lock lock = new Lock();
        private int count = 0;
        public int inc(){
            lock.lock();
            int newCount = ++count;
            lock.unlock();
            return newCount;
        }
    }
    
    
    1. 使用局部变量实现线程同步
      注:ThreadLocal与同步机制
      a.ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题。
      b.前者采用以"空间换时间"的方法,后者采用以"时间换空间"的方式
    2. 使用阻塞队列实现线程同步
      ● 使用LinkedBlockingQueue<E>来实现线程的同步
      ● LinkedBlockingQueue<E>是一个基于已连接节点的,范围任意的blocking queue。
    3. ReentrantLock公平策略锁---公平在等待时间最长的线程首先获得锁

    相关文章

      网友评论

          本文标题:多线程之线程同步

          本文链接:https://www.haomeiwen.com/subject/tvmplxtx.html