synchronized关键字介绍
java提供关键字synchronized用来防止多个线程对同一临界区进行访问时,产生的资源冲突。要解决资源冲突就要引入一个锁的概念,
所有的对象都含有单一的锁,。
synchronized可以用来修饰非静态方法
public synchronized void a(){
*******
};
修饰同步代码块
public synchronized void a(){
synchronized(this){
*******
}
};
你可以把可能在多线程访问下发生冲突的代码段放到,同步代码块中,而不是修饰整个函数,被synchronized修饰的方法是很影响多线程性能的,虽然保证了程序的正确运行,更推荐使用同步代码块。同步代码块需要一个Object的参数,表示谁获取了这个Object的对象锁,那个线程就能运行这段代码块的内容,其他线程将会阻塞,如果参数为this就表示获取的是当前对象的锁。
当多个线程调用同一个对象中被synchronized修饰的某一个方法时,该对象都会被加锁,该对象的其他被synchronized修饰的方法只有等到该方法执行完后,对象的锁被释放后才有可能获得执行的机会(只针对于其他线程而言无法调用别的被synchronized修饰的方法,当前线程可以
package com.thread.study;
class A {
public synchronized void a() {
System.out.println(" i am a synchronized static function");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("release the lock");
}
public synchronized void b() {
System.out.println(" try get lock");
}
}
public class SynchronizedTest {
public static void main(String[] args) {
A a = new A();
Thread one = new Thread(new Runnable() {
public void run() {
a.a();
}
});
one.start();
Thread two = new Thread(new Runnable() {
public void run() {
a.b();
}
});
two.start();
}
}
2个线程分别调度a对象中的a()方法和b()方法,a()运行时会沉睡5秒,使用Thread.sleep()方式,不会释放锁,而调用wait()方法是当前线程会释放锁,然后进入阻塞状态。当a()被one线程运行时,试图运行b()方法的线程阻塞至one线程运行完。结果如下
synchronized 修饰静态的方法和修饰类
public synchronized static void a(){
*******
};
public synchronized A(){
*******
};
静态的方法是直接和类挂钩的,当调用被synchronized修饰的静态方法,当一个线程调用其中的一个静态方法时,其他线程试图调用该类的该静态方法或其他静态方法时都会被阻塞,让我们修改一下上面的例子
package com.thread.study;
class A {
public synchronized static void a() {
System.out.println(" i am a synchronized static function");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("release the lock");
}
public synchronized static void b() {
System.out.println(" try get lock");
}
}
public class SynchronizedTest {
public static void main(String[] args) {
A a = new A();
Thread one = new Thread(new Runnable() {
public void run() {
A.a();
}
});
one.start();
Thread two = new Thread(new Runnable() {
public void run() {
A.b();
}
});
two.start();
}
}
结果
是一样的,但是如果b()方法如果不是静态的,two线程访问时不会被阻塞,
package com.thread.study;
class A {
public synchronized static void a() {
System.out.println(" i am a synchronized static function");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("release the lock");
}
public synchronized void b() {
System.out.println(" try get lock");
}
}
public class SynchronizedTest {
public static void main(String[] args) {
A a = new A();
Thread one = new Thread(new Runnable() {
public void run() {
A.a();
}
});
one.start();
Thread two = new Thread(new Runnable() {
public void run() {
a.b();
}
});
two.start();
}
}
结果如下
因为static 的a()方法是和类绑定的,而b方法是和对象a绑定的。