其实关于加锁一直不是特别清晰,今天梳理一遍:
一、在函数声明上添加syn关键字,一旦一个线程获取了一个方法的锁,则其他线程均不能调用带有syn关键字声明的方法:
public class funLockTest {
public static void main(String[] args) {
final funLock fl = new funLock();
new Thread(fl).start();
try {
//添加sleep是为了保证让f()先运行起来
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
fl.g();
}
}
class funLock implements Runnable{
public synchronized void f(){
System.out.println("f() finished!");
while(true);
}
public synchronized void g(){
System.out.println("g() started!");
}
public void run(){
f();
}
}
输出为:f() finished!并保持死循环,g()永远得不到执行。
二、如果使用syn(this)编写同步代码块,将一个对象内标有syn的方法全部加锁,下面这个例子可以看到,syn(this)只是获取对象上同步方法的锁,非同步方法在其他线程依然是可以访问的。我之前以为加了syn(this)代表获取对象上所有资源的访问权限,这是不对的!
public class funLockTest {
public static void main(String[] args) {
final funLock fl = new funLock();
new Thread(fl).start();
try {
//添加sleep是为了保证让f()先运行起来
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
fl.m();
fl.g();
}
}
class funLock implements Runnable{
public void f(){
synchronized(this){
System.out.println("f() finished!");
while(true);
}
}
public synchronized void g(){
System.out.println("g() started!");
}
public void m(){
System.out.println("None synchronized m() finished!");
}
public void run(){
f();
}
}
代码输出:
f() finished!
None synchronized m() finished!
三、同一个线程获取了带有syn关键字的锁,则他可以继续在此对象上继续获取锁。main线程通过f()获取了this对象的锁,但是在锁释放之前依然可以进入g()方法。
public class funLockTest {
public static void main(String[] args) {
final funLock fl = new funLock();
fl.f();
}
}
class funLock{
private static int count = 10;
public void f(){
synchronized(this){
count--;
System.out.println("f() finished!");
g();
}
}
public synchronized void g(){
if(count < 0)
return;
System.out.println("g() started!");
count--;
f();
}
}
输出:
f() finished!
g() started!
f() finished!
g() started!
f() finished!
g() started!
f() finished!
g() started!
f() finished!
g() started!
f() finished!
四、当在其他对象上加锁时,与外部对象上的锁是相互独立的。在o1对象上加的锁并不会影响主线程对g()的调用。
public class funLockTest {
public static void main(String[] args) {
final funLock fl = new funLock();
new Thread(fl).start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
fl.g();
}
}
class funLock implements Runnable{
Object o1 = new Object();
public void f(){
synchronized(o1){
System.out.println("f() finished!");
while(true);
}
}
public synchronized void g(){
System.out.println("g() started!");
f();
}
public void run(){
f();
}
}
输出:
f() finished!
g() started!