Java中synchronized可以在多线程下做线程安全的同步锁,本文针对synchronized的使用及使用范围进行实例讨论
下面分别就对象锁和类锁进行分析
对象锁
非静态方法使用synchronized修饰的写法,锁定的是当前对象,例如
实例一:
public class Sync {
private static final String TAG = "Sync";
public synchronized void test1() {
Log.e(TAG, "test1 start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG, "test1 end");
}
public synchronized void test2() {
Log.e(TAG,"test2 start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG,"test2 end");
}
}
public class ThreadDemo4Activity extends Activity {
private static final String TAG = "ThreadDemo2Activity";
Sync sync;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo3_ui);
sync = new Sync();
Thread2 thread2= new Thread2();
thread2.start();
Thread3 thread3= new Thread3();
thread3.start();
}
class Thread2 extends Thread{
@Override
public void run() {
sync.test1();
}
}
class Thread3 extends Thread{
@Override
public void run() {
sync.test2();
}
}
}
其打印结果如下:
07-09 15:39:30.073 24633-25111/com.yang.test E/Sync: test1 start
07-09 15:39:32.073 24633-25111/com.yang.test E/Sync: test1 end
07-09 15:39:32.074 24633-25112/com.yang.test E/Sync: test2 start
07-09 15:39:33.075 24633-25112/com.yang.test E/Sync: test2 end
实例一总结,一个类中有两个方法,两个方法都加了synchronized修饰,开两个线程分别调用同对象的两个方法,经过测试,打印出的Log,可以看到一个方法调用了,该对象的其他同步的方法就锁定了,等到该方法执行结束,才释放该对象其他的同步方法的锁。
实例二:
public class Sync {
private static final String TAG = "Sync";
public synchronized void test1() {
Log.e(TAG, "test1 start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG, "test1 end");
}
public void test2() {
Log.e(TAG,"test2 start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG,"test2 end");
}
}
执行结果:
07-09 15:47:00.099 25633-25730/com.yang.test E/Sync: test1 start
07-09 15:47:00.100 25633-25731/com.yang.test E/Sync: test2 start
07-09 15:47:01.101 25633-25731/com.yang.test E/Sync: test2 end
07-09 15:47:02.100 25633-25730/com.yang.test E/Sync: test1 end
实例二总结:相同的类,两个方法,一个加了synchronized同步锁,一个没加synchronized同步锁,开两个线程分别调用同一对象的两个方法,打印的Log可以看出,当调用了该对象的同步方法,并未锁定该对象的非同步的方法。
类锁
类锁有两种方法:一种是写在某个类里面的静态方法上或者使用在代码块上,例如:
实例三静态方法 :
public static synchronized void test2() {
Log.e(TAG,"Sync2 test start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG,"Sync2 test end");
}
调用
package com.yang.test.demo3;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import com.yang.test.R;
public class ThreadDemo3Activity extends Activity {
private static final String TAG = "ThreadDemo3Activity";
Sync2 sync;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo3_ui);
/*sync = new Sync2();
for(int i=0;i<2;i++){
Thread1 thread1 = new Thread1(sync);
thread1.start();
}*/
sync = new Sync2();
for(int i=0;i<2;i++){
Thread2 thread2 = new Thread2(sync);
thread2.start();
}
}
class Thread1 extends Thread{
Sync2 sync ;
public Thread1(Sync2 sync) {
this.sync = sync;
}
@Override
public void run() {
sync.test1();
}
}
class Thread2 extends Thread{
Sync2 sync ;
public Thread2(Sync2 sync) {
this.sync = sync;
}
@Override
public void run() {
sync.test2();
}
}
}
运行结果:
07-09 16:01:32.836 26679-26747/com.yang.test E/Sync2: Sync2 test start
07-09 16:01:34.837 26679-26747/com.yang.test E/Sync2: Sync2 test end
07-09 16:01:34.838 26679-26746/com.yang.test E/Sync2: Sync2 test start
07-09 16:01:36.839 26679-26746/com.yang.test E/Sync2: Sync2 test end
实例四代码块上:
public void test1() {
synchronized (Sync2.class) {
Log.e(TAG,"Sync2 test start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG,"Sync2 test end");
}
}
调用:
package com.yang.test.demo3;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import com.yang.test.R;
public class ThreadDemo3Activity extends Activity {
private static final String TAG = "ThreadDemo3Activity";
Sync2 sync;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo3_ui);
sync = new Sync2();
for(int i=0;i<2;i++){
Thread1 thread1 = new Thread1(sync);
thread1.start();
}
/* sync = new Sync2();
for(int i=0;i<2;i++){
Thread2 thread2 = new Thread2(sync);
thread2.start();
}*/
}
class Thread1 extends Thread{
Sync2 sync ;
public Thread1(Sync2 sync) {
this.sync = sync;
}
@Override
public void run() {
sync.test1();
}
}
class Thread2 extends Thread{
Sync2 sync ;
public Thread2(Sync2 sync) {
this.sync = sync;
}
@Override
public void run() {
sync.test2();
}
}
}
运行结果如下:
07-09 16:05:25.588 26990-27123/com.yang.test E/Sync2: Sync2 test start
07-09 16:05:27.589 26990-27123/com.yang.test E/Sync2: Sync2 test end
07-09 16:05:27.589 26990-27122/com.yang.test E/Sync2: Sync2 test start
07-09 16:05:29.589 26990-27122/com.yang.test E/Sync2: Sync2 test end
类锁总结:实例三和实例四,静态类和代码块,锁定类和对象锁很类似,都能达到线程同步的效果
下面我们再来测试一个案例:
同一个类中,一个方法是静态同步方法,一个是非静态同步方法,看看效果如何呢?
案例五:
package com.yang.test.demo3;
import android.util.Log;
public class Sync3 {
private static final String TAG = "Sync1";
public static synchronized void test1() {
Log.e(TAG, "test1 start");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG, "test1 end");
}
public synchronized void test2() {
Log.e(TAG,"test2 start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG,"test2 end");
}
}
调用:
package com.yang.test.demo3;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import com.yang.test.R;
public class ThreadDemo5Activity extends Activity {
private static final String TAG = "ThreadDemo2Activity";
Sync1 sync;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.demo3_ui);
sync = new Sync1();
Thread2 thread2= new Thread2();
thread2.start();
Thread3 thread3= new Thread3();
thread3.start();
}
class Thread2 extends Thread{
@Override
public void run() {
Sync3.test1();
}
}
class Thread3 extends Thread{
@Override
public void run() {
sync.test2();
}
}
}
其运行结果如下:
07-09 16:14:31.716 27597-27629/com.yang.test E/Sync1: test1 start
07-09 16:14:31.718 27597-27630/com.yang.test E/Sync1: test2 start
07-09 16:14:32.719 27597-27630/com.yang.test E/Sync1: test2 end
07-09 16:14:33.717 27597-27629/com.yang.test E/Sync1: test1 end
对象锁和类锁区别:
1、对象锁和类锁是相互独立的,互补干扰
2、对象锁锁定当前对象,类锁锁定整个类
3、一个类中两个方法,一个静态方法,一个非静态方法,都加了synchronized,静态方法为类锁,非静态方法为对象锁