1.作用及版本
JDK1.6以前的synchronized是一把重量级锁,监视器锁(monitor),当一个线程获取到锁之后,其他线程想要获取锁就必须等待,也就是其他线程是阻塞状态(Blocked)。当前线程获取到锁执行完之后释放锁,这时阻塞队列里面的线程会去竞争锁,竞争到锁的线程又继续执行。由于这个时候发生了线程切换,因此操作系统由用户态变成核心态,这个过程是比较耗时的,因此在JDK1.6以后对synchronized关键字进行了优化。
2.作用域
静态方法:相当于类锁,所有对象共享类锁。
package com.sap.leo;
public class Concurrency extends Thread{
private static int data = 0;
public Concurrency(String name)
{
super(name);
}
public static void main(String[] args) throws InterruptedException {
Concurrency c1 = new Concurrency("c1");
Concurrency c2 = new Concurrency("c2");
Concurrency c3 = new Concurrency("c3");
Concurrency c4 = new Concurrency("c4");
c1.start();
c2.start();
c3.start();
c4.start();
Thread.sleep(60*2*1000);
}
@Override
public void run() {
synchronized (Concurrency.class)
{
try {
if(Thread.currentThread().getName().equals("c1"))
{
Thread.currentThread().sleep(60000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
非静态方法:对象锁;
package com.sap.leo;
public class Concurrency extends Thread{
public static void main(String[] args) throws InterruptedException {
Concurrency c = new Concurrency();
Thread t1 = new Thread(c,"t1");
Thread t2 = new Thread(c,"t2");
Thread t3 = new Thread(c,"t3");
Thread t4 = new Thread(c,"t4");
t1.start();
t2.start();
t3.start();
t4.start();
Thread.sleep(10000);
}
@Override
public synchronized void run()
{
if("t1".equals(Thread.currentThread().getName()))
{
System.out.println("t1 get lock...");
System.out.println("t1 sleep 5s...");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t1 release lock...");
}
else
{
System.out.println(Thread.currentThread().getName());
}
}
}
3.字节码层面分析
package com.sap.leo;
public class Concurrency {
private int data = 0;
public static void main(String[] args) throws InterruptedException {
Concurrency c = new Concurrency();
for(int i=0;i<1000;i++)
{
new Thread(()->{
c.manipulateData();
}).start();
}
Thread.sleep(5000);
System.out.println(c.data);
}
public int manipulateData()
{
synchronized (this)
{
data++;
}
return this.data;
}
}
4.synchronized滥用:死锁
package com.sap.leo.concurrency;
public class DeadLock
{
private static String resource1 = "r1";
private static String resource2 = "r2";
public static void main(String[] args)
{
Thread t1 = new Thread(new Runnable()
{
@Override
public void run()
{
synchronized (resource1)
{
System.out.println("Thread "+ Thread.currentThread().getName() + " got resource1..." );
long startTime = System.currentTimeMillis();
System.out.println("Wait for getting resource2... ");
try
{
Thread.currentThread().sleep(1000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (resource2)
{
System.out.println("Thread "+ Thread.currentThread().getName() + " got resource2..." );
}
}
}
}, "t1");
t1.start();
Thread t2 = new Thread(new Runnable()
{
@Override
public void run()
{
Thread.currentThread().yield();
synchronized (resource2)
{
System.out.println("Thread "+ Thread.currentThread().getName() + " got resource2..." );
try
{
System.out.println("Wait for getting resource1... ");
Thread.currentThread().sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
synchronized (resource1)
{
System.out.println("Thread "+ Thread.currentThread().getName() + " got resource1..." );
}
}
}
}, "t2");
t2.start();
}
}
5.synchronized锁优化技术(JDK1.6以后)