1、synchronized
(1)关键字synchronized取得的锁都是对象锁,而不是把一段代码或方法当作锁。
对象方法内的临时变量为线程安全的,对象的成员变量(实例变量)为非线程安全的。
public class MyObject {
synchronized public void methodA() {
try {
System.out.println("begin methodA threadName="+Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("end methodA endTime="+System.currentTimeMillis());
}catch( InterruptedException e) {
e.printStackTrace();
}
}
synchronized public void methodB() {
try {
System.out.println("begin methodB thread-"+Thread.currentThread().getName()+" beginTime="+System.currentTimeMillis());
Thread.sleep(5000);
System.out.println("end methodB endTime="+System.currentTimeMillis());
}catch( InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadA extends Thread {
private MyObject object;
public ThreadA(MyObject object) {
this.object=object;
}
@Override
public void run() {
super.run();
this.object.methodA();
}
}
public class ThreadB extends Thread {
private MyObject object;
public ThreadB(MyObject object) {
this.object=object;
}
@Override
public void run() {
super.run();
this.object.methodB();
}
}
public class Run {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyObject object=new MyObject();
ThreadA a=new ThreadA(object);
a.setName("A");
ThreadB b=new ThreadB(object);
b.setName("B");
a.start();
b.start();
}
}
当A线程调用object对象加入synchronized关键字的X方法时,A线程就获得了X方法所在对象的锁,其他线程必须等A线程执行完毕后才可以调用X方法和其他具有synchronized关键字的非X方法。
(2)synchronized具有锁重入功能
即在一个synchronized方法/块的内部调用本类的其他synchronized方法/块时,是永远可以得到锁的。
public class Service {
synchronized public void service1() {
System.out.println("service1");
this.service2();
}
synchronized public void service2() {
System.out.println("service2");
this.service3();
}
synchronized public void service3() {
System.out.println("service3");
}
}
可重入锁也支持再父子继承的环境中。即在子类的synchronized方法中调用父类的synchronized方法。
(3)synchronized不具有继承性。
在子类方法重写父类synchronized方法时,必须显示的写出synchronized关键字,否则子类的该方法不具有同步性。
(4)synchronized代码块/方法中出现异常时,锁会自动释放。
(5)synchronized(非this 对象x)代码块中的程序与synchronized(this)中的程序是异步的,不与其他同步方法争抢this锁。
1、当多个线程同时执行synchronized(x){}同步代码块时呈现同步效果
2、当其它线程执行x对象中synchronized同步方法是呈现同步效果
3、当其它线程执行x对象中synchronized同步方法块时也呈现同步效果。
(6)synchronized加到static静态方法上是给Class类上锁,同一个类的不同对象只能同步访问该方法;
而加到非static方法上,则是同一个对象在不同线程间只能同步访问该方法。
(7)一般同步synchronized代码块不使用String作为锁对象,而用一个实例化对象比如new Object(),这是因为JVM中具有String常量池缓存功能。
2、volatile关键字
强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值。
不具有将线程工作内存的变量与公共内存中的变量同步的功能。因为变量在内存中的load、use、assign操作具有非原子性。
除了使用synchronized外,可以采用将变量声明为原子类的方法实现同步,如:AtomicInteger count(声明一个整型变量count)。
同步synchronized不仅可以解决一个线程看到对象处于不一致的状态,还可以保证进入同步方法/代码块的每个线程,都看到由同一个锁保护之前所有的修改效果。
public class Service {
private boolean isContinue=true;
public void runMethod() {
String any=new String();
while(isContinue==true) {
synchronized(any) {
/*一旦isContinue的值在其他线程被修改,会立刻反映到当前线程中*/
}
}
}
public void stopMethod() {
this.isContinue=false;
}
}