同步(synchronized):
Java对于多线程的安全问题提供了专业的解决方式:同步机制。
同步的方式,解决了线程的安全问题。——好处
操作同步代码时,只能有一个线程参与,其他线程等待,相当于一个单线程,效率低下。——局限性
synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
synchronized的使用方法(三种):
方法一(同步代码块):
synchronized(同步监视器(又称锁)){
//需要被同步的代码
}
同步代码块:自己指定,很多时候也是指定为this或类名.class
说明:
1、操作共享数据(多个线程共同操作的变量)的代码,就是需要被同步的代码。
2、同步监视器,任何一个类的对象都可以充当锁,所有对象都自动含有单一的锁(监视器).
要求:
多个线程必须共用同一把锁。
方法二(同步方法):
private static synchronized void show() {
...//需要被同步的代码
}
同步方法的锁:静态方法(类名.class)、非静态方法(this)
关于同步方法的总结:
1、同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。
2、非静态的同步方法,同步监视器:this; 静态的同步方法,同步监视器:当前类本身。
以下几种情况会释放锁:
1、当同步方法、同步代码块执行完。
2、当同步方法、同步代码块遇到break、return终止了代码块。
3、当同步方法、同步代码块未处理的Error和Exception,导致结束。
4、当同步方法、同步代码块中执行了线程对象的wait()方法,当前线程暂停,并释放锁。
注:调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行。
方法三(Lock锁——JDK5.0新增):
java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。
格式:
import java.util.concurrent.locks.ReentrantLock;//调用包
class A{
private final ReentrantLock lock = new ReenTrantLock();
public void m(){
lock.lock();//上锁
try{
//保证线程安全的代码;
}
finally{
lock.unlock();//调用解锁方法
}
}
}
synchronized和Lock的区别:
1、Lock是显式锁(手动开启和关闭锁),synchronized是隐式锁,出了作用域自动释放。
2、Lock只有代码块锁,synchronized有代码块锁和方法锁。
3、使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且有更好的扩展性(提供更多的子类)。
关于单例模式的懒汉式(线程安全的单例模式):
eg:
class Bink{
private Bink(){
}
private static Bink instance = null;
public static Bink getInstance() {
if(instance == null) { //多加了一个判断
synchronized(Bink.class){
if(instance == null){
instance = new Bink();
}
}
}
return instance;
}
}
若有不当之处,欢饮指正!!!