Java多线程同步

synchronized关键字
  • synchronized关键字修饰函数方法
    使用synchronized关键字时,会获取java对象的内置锁,内置锁会保护整个方法。
public synchronized void add(){
    count++;
}

synchronized也可以修饰静态方法,内置锁会锁住整改类。

  • synchronized关键字修饰代码块
    synchronized可以修饰代码块,只锁住需要保护的代码区域
public class SynchronizedThread {
    public void add(){
        synchronized(this)
        {
            count++;
        }
     }
}

synchronized是一种高开销操作,实际应用不需要锁住整个方法,可以使用同步代码块操作。

使用特殊域变量

使用volatile关键字修饰变量,没有锁同步开销,每次使用变量时需要重新计算,不会直接使用寄存器的值,此变量不是原子操作,不可以修饰final对象。

public class SynchronizedThread{
    private volatile int count= 0;
    public void add(){
        count++;
    }
}
使用原子变量实现线程同步

在java的util.concurrent.atomic包中提供了创建了原子类型变量的工具类,使用该类可以简化线程同步。

public class SynchronizedThread{
    private AtomicInteger count= new AtomicInteger(0);
    public void add(){
        count.addAndGet(1);
    }
}

原子操作适合线程简单对象的计算。

使用重入锁实现线程同步

在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。ReentrantLock类是可重入、互斥、实现了Lock接口的锁,它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力。

public class SynchronizedThread{
    private int count= 0;
    private Lock lock = new ReentrantLock();
    public void add(){
        lock.lock();
        try{
             count++;
        }finally{
             lock.unlock();
        }
    }
}

使用try模块语句,在finally模块中释放锁,防止死锁。
ReentrantLock类可以构造公平锁,每个线程阻塞相同的时间,但由于能大幅度降低程序运行效率,不推荐使用。

使用局部变量实现线程同步

如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本, 副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。

public class SynchronizedThread{
    private static ThreadLocal count= new ThreadLocal(){
        @Override
        protected Integer initialValue(){
            return 0;
        }
    };
    public void add(){
        count.set(count.get()+1);
    }
}
使用阻塞队列实现线程同步

前面5种同步方式都是在底层实现的线程同步,但是我们在实际开发当中,应当尽量远离底层结构。 使用javaSE5.0版本中新增的java.util.concurrent包将有助于简化开发。 本小节主要是使用LinkedBlockingQueue来实现线程的同步。

public class BlockingSynchronizedThread {
    private LinkedBlockingQueue queue = new LinkedBlockingQueue();
    private class LinkBlockThread implements Runnable {
        @Override
        public void run() {
            try {
                int n = queue.take();
                System.out.println(n);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

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