java synchronized理解

synchronized是Java中的关键字,是一种同步锁 它能够用来修饰方法和代码块多线程

多线程的状况下 synchronized 修饰的方法和代码块会让一个线程执行(锁住代码),另外的线程等待ide

下面咱们经过一个例子来看下spa

public class Synchronized {
	public  void test(String tag) {
        if ("a".equals(tag)) {
			System.out.println("a");
			
		} else if ("b".equals(tag)) {
			System.out.println("b");
		}
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println("the end");

	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		final Synchronized s1 = new Synchronized();
		final Synchronized s2 = new Synchronized();
		Thread t1 = new Thread(new Runnable(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				s1.test("a");
			}
			
		},"t1");
		Thread t2 = new Thread(new Runnable(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				s2.test("b");
			}
			
		},"t2");
		t1.start();
		t2.start();

	}

}

启动两个线程 调用方法 test 运行结果是这样的  这是没加synchronized 关键字的状况,线程

(屡次运行结果可能不一样)code

a
当前线程:t1
b
当前线程:t2
the end
the end

这个结果表示一个线程不会等到另外一个线程执行完再执行对象

若是是一个线程等待另外一个线程执行完的话 打印结果应该是get


当前线程:t1
the end 

当前线程:t2
the end同步

或者 class


当前线程:t2
the endtest


当前线程:t1
the end 

 

下面 咱们在 test方法上加 synchronized 关键字看下打印结果

public class Synchronized {
    // 加 synchronized  修饰
	public  synchronized void test(String tag) {

		if ("a".equals(tag)) {
			System.out.println("a");
			
		} else if ("b".equals(tag)) {
			System.out.println("b");
		}
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println("the end");

	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		final Synchronized s1 = new Synchronized();
		final Synchronized s2 = new Synchronized();
		Thread t1 = new Thread(new Runnable(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				s1.test("a");
			}
			
		},"t1");
		Thread t2 = new Thread(new Runnable(){

			@Override
			public void run() {
				// TODO Auto-generated method stub
				s2.test("b");
			}
			
		},"t2");
		t1.start();
		t2.start();

	}

}

运行结果 

a
b
当前线程:t1
the end
当前线程:t2
the end

       发如今方法上加上 synchronized关键字后 仍是没有实现一个线程执行时(锁住代码),另外的线程等待执行完后再执行的效果。

      咱们来看下代码

  t1线程启动 调用s1.test();方法 

  这个方法在执行的时候 是看到了test synchronized 关键字的 因此方法执行的时候线程会先去尝试得到对象锁,这时候 的锁就是对象s1的锁,

 t2线程启动 调用s2.test()方法

 一样t2线程在执行到test方法时也看到了 synchronized 关键字 因此这时候线程也会去尝试得到对象锁 ,

若是这时候,对象锁被其余线程得到了 那么t2线程就进入阻塞 等待状态 ,

   咱们开始会认为 t2线程走到s2.test()的时候 t1线程已经得到了锁,因此t2线程这会会阻塞,

但实际上t1线程得到的是 s1的锁,t2执行到 test方法时 要判断锁是否被其余线程得到,这个锁是s2的对象锁,两个线程得到的锁是不一样对象的 因此相互间不影响 ,因此这两个线程不会等到另一个线程执行完再执行

咱们换一种写法让  不一样的线程调用到test方法时要获取的对象锁是同样的

public class Synchronized {
	public   void test(String tag) {

		if ("a".equals(tag)) {
			System.out.println("a");
			
		} else if ("b".equals(tag)) {
			System.out.println("b");
		}
		System.out.println("当前线程:"+Thread.currentThread().getName());
		System.out.println("the end");

	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		final Synchronized s1 = new Synchronized();
		final Synchronized s2 = new Synchronized();
        //这里lock 只是对象的名字 由于功能上比较像锁 因此就取这名 跟jdk里面的Lock不要紧 
        // 后面线程执行的时候都会先获取到这个对象的锁 一个线程只有在方法执行完后 才会把这个对象的锁释放掉
		final Object lock = new Object();
		Thread t1 = new Thread(new Runnable(){

			@Override
			public void run() {
				synchronized (lock) {
					// TODO Auto-generated method stub
					s1.test("a");
				}
			}
			
		},"t1");
		Thread t2 = new Thread(new Runnable(){

			@Override
			public void run() {
				synchronized (lock) {
					// TODO Auto-generated method stub
					s2.test("b");
				}
			}
			
		},"t2");
		t1.start();
		t2.start();

	}

}

这时候的运行结果就知足咱们的预期了。

 

synchronized 修饰 static 方法

方法加上static 后就是类的方法了 不属于任何对象 这时候在方法上在加上synchronized 修饰 做用的对象是这个类的全部对象,

像前面说的 test 方法 加了 synchronized 修饰后 再加 static 修饰 也能实现 一个线程等待另一个线程执行完的效果

相关文章
相关标签/搜索