线程同步synchronized

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");
				}
			}
		}
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值