synchronized只是保证在同一个时刻,其他线程不能访问锁定的资源,但是其他方法或者是变量不能锁定控制的
synchronized(obj){
...
//此处的代码就是同步代码块
}
上面语法格式中synchronized后括号里的obj就是同步监视器,上面代码的含义是:线程开始执行同步代码块之前,必须先获得对同步监视器的锁定。
任何时刻只能有一个线程可以获取对同步监视器的锁定,当同步代码块执行完之后,该线程会释放对该同步监视器的锁定。
同步监视器的目的:阻止两个线程对同一个共享资源进行并发访问,因此通常推荐使用可能被并发访问的共享资源充当同步监视器。
使用synchronized关键字来修饰某个方法,则该方法称为同步方法。对于同步方法而言,无须显示指定同步监视器,同步方法的同步监视器是this,也就是该对象本身。
使用同步方法可以非常方便的实现线程安全类,线程安全类具有如下特征:
1、该类的对象可以被多个线程安全的访问
2、每个线程调用该对象的任意方法之后都将得到正确结果
3、每个线程调用该对象的任意方法之后,该对象的状态依然保持合理状态。
synchronized可以修饰方法、代码块,但是不能修饰构造器和属性等。
解决死锁办法之一:
1、将锁的粒度放粗一点(一口气锁住所有资源)
public class TraditionalThreadSynchronized {
public static void main(String[] args) {
new TraditionalThreadSynchronized().init();
}
private void init(){
final Outputer outputer = new Outputer();
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output("zhangxiaoxiang");
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
outputer.output3("lihuoming");
}
}
}).start();
}
static class Outputer{
public void output(String name){
int len = name.length();
synchronized (Outputer.class)
{
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
public synchronized void output2(String name){
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
public static synchronized void output3(String name){
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
备注:如果同步方法是“静态方法”,则同步监视器应该是“字节码”
可以简单的模拟死锁的情况
public class TestDeadLockMain {
public static void main(String[]args){
TestDeadLock t1 = new TestDeadLock();
TestDeadLock t2 = new TestDeadLock();
t1.setFlag(0);
t2.setFlag(1);
Thread thread1 = new Thread(t1);
Thread thread2 = new Thread(t2);
thread1.start();
thread2.start();
}
}
package hb.thread;
public class TestDeadLock implements Runnable {
public int flag = 1;
public Object obj1 = new Object();
public Object obj2 = new Object();
public void setFlag(int flag){
this.flag = flag;
}
@Override
public void run() {
if(0 == flag){
synchronized(obj1){
try {
System.out.println("flag = " + flag);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized(obj2){
System.out.println("second obj2");
}
}
}
if(1 == flag){
synchronized(obj2){
try {
System.out.println("flag = " + flag);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized(obj1){
System.out.println("second obj1");
}
}
}
}
}