多线程之线程同步

同步的方法:

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来实现线程的同步
    ● LinkedBlockingQueue是一个基于已连接节点的,范围任意的blocking queue。
  3. ReentrantLock公平策略锁---公平在等待时间最长的线程首先获得锁

你可能感兴趣的:(多线程之线程同步)