java中多线程中的同步机制会对资源进行加锁,保证在同一时间只有一个线程可以操作资源,避免多线程同时访问相同资源发生冲突。
Synchronized是java中的关键字,它是一种同步锁,可以实现同步机制。
Synchronized修饰对象主要有以下三种:
-
修饰普通方法
- 一个对象中的加锁方法只允许一个线程访问。但要注意‘这种情况下锁的是访问该方法的实例对象,如果多个线程不同对象访问该方法,则无法保证同步
-
修饰静态方法
- 由于静态方法是类方法,所以这个方法锁的是包含这个方法的类,也就是类对象;这样如果多个线程不同的对象访问该静态方法,也是可以保证同步的。
-
修饰代码块
- 修饰普通代码块和修饰普通方法一样;
- Synchronized静态代码块它的同步效果和修饰方法类似
- 其中Synchronized(obj)这里的obj可以为类的一个属性、也可以是当前的对象。
Synchronized修饰方法和代码块的区别:
Synchronized方法控制范围较大,它会同步对象中所有的Synchronized方法的代码。
Synchronized代码块控制范围较小,它只会同步代码块中的代码,而位于代码块之外的代码是可以被多个线程访问的。
简单来说 就是Synchronized代码块更加灵活精确。
测试代码如下:
private SynchronizedTest synchronizedTest;
private void testSynchrnoized() {
synchronizedTest = new SynchronizedTest();
//测试synchronized修饰普通方法
//testCommon();
//测试synchronized修饰静态方法
//testStatic();
//测试synchronized修饰代码块
testArea();
}
private void testArea() {
new Thread(new Runnable() {
@Override
public void run() {
synchronizedTest.setAge2(0);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
SynchronizedTest test = new SynchronizedTest();
test.setAge2(1);
}
}).start();
}
private void testStatic() {
new Thread(new Runnable() {
@Override
public void run() {
synchronizedTest.setAge1(0);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
SynchronizedTest test = new SynchronizedTest();
test.setAge1(1);
}
}).start();
}
private void testCommon() {
new Thread(new Runnable() {
@Override
public void run() {
synchronizedTest.setAge(0);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronizedTest.setAge(1);
}
}).start();
}
SynchronizedTest类代码如下:
public class SynchronizedTest {
public int age;
public int getAge() {
return age;
}
/**
* 修饰普通方法:一个对象中的加锁方法只允许一个线程访问。但要注意‘这种情况下锁的是访问该方法的实例对象,如果多个线程不同对象访问该方法,则无法保证同步’
*
* @param age
*/
public synchronized void setAge(int age) {
if (age == 0) {
Log.e("result", "Thread0进来访问了");
} else {
Log.e("result", "Thread1进来访问了");
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 修饰静态方法: 由于静态方法是类方法,所以这个方法锁的是包含这个方法的类,也就是类对象;这样如果多个线程不同的对象访问该静态方法,也是可以保证同步的。
*
* @param age
*/
public synchronized static void setAge1(int age) {
if (age == 0) {
Log.e("result", "Thread0进来访问了");
} else {
Log.e("result", "Thread1进来访问了");
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static SynchronizedTest instance;
public static SynchronizedTest getInstance(){
if(instance == null){
synchronized (SynchronizedTest.class){
instance = new SynchronizedTest();
}
}
return instance;
}
/**
* 修饰代码块:
* 1. 修饰普通代码块和修饰普通方法一样;
* 2. Synchronized静态代码块它的同步效果和修饰方法类似
* 3. 其中Synchronized(obj)这里的obj可以为类的一个属性、也可以是当前的对象。
* @param age
*/
public static void setAge2(int age) {
synchronized (SynchronizedTest.class) {
if (age == 0) {
Log.e("result", "Thread0进来访问了");
} else {
Log.e("result", "Thread1进来访问了");
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
网友评论