synchronized关键字

1、synchronized关键字:

1)、可用来修饰一个方法或代码块
2)、作用:保证在同一时刻只能有一个线程来访问当前对象的这段代码

2、例子(对代码块加锁,两个线程同时跑,一定要等第一个线程执行完跑完,第二个才执行):

package com.sxit.test;

public class Test implements Runnable{

	public static void main(String[] args) {
		
		Test test1 = new Test();
		Thread thread1 = new Thread(test1,"线程1");
		Thread thread2 = new Thread(test1,"线程2");
		
		thread1.start();
		thread2.start();
	}
	
	public void run() {
		//对当前对象加锁,同一时刻只能有一个线程持有当前对象的锁,一定要等第一个线程执行完,锁释放后,第二个线程才开始跑
		synchronized (this) {
			for(int i = 0 ;i<50;i++){
				System.out.println("当前线程是:"+Thread.currentThread().getName()+"------>>>跑到"+i);
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}


-----------打印信息(太长,只截取一部分)-----------
当前线程是:线程1------>>>跑到0
当前线程是:线程1------>>>跑到1
当前线程是:线程1------>>>跑到2
当前线程是:线程1------>>>跑到3
当前线程是:线程1------>>>跑到4
当前线程是:线程1------>>>跑到5
。。。。。。。。。。。。。。。。。
当前线程是:线程1------>>>跑到49
当前线程是:线程2------>>>跑到0
当前线程是:线程2------>>>跑到1
当前线程是:线程2------>>>跑到2
当前线程是:线程2------>>>跑到3
当前线程是:线程2------>>>跑到4
当前线程是:线程2------>>>跑到5
当前线程是:线程2------>>>跑到6
。。。。。。。。。。。。。。。。。
当前线程是:线程2------>>>跑到49

3、例子(一个线程访问当前对象同步方法,另外一个线程可以访问该对象的非同步方法):

package com.sxit.test;

public class Test implements Runnable{

	public static void main(String[] args) {
		
		Test test1 = new Test();
		//启一个线程
		Thread thread1 = new Thread(test1,"线程1");
		
		thread1.start();
		//当前线程执行test方法
		test1.test();
	}
	
	public void run() {
		//对当前对象加锁,同一时刻只能有一个线程持有当前对象的锁,一定要等第一个线程执行完,锁释放后,第二个线程才开始跑
		synchronized (this) {
			for(int i = 0 ;i<50;i++){
				System.out.println("当前线程是:"+Thread.currentThread().getName()+"------>>>跑到"+i);
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public void test(){
		try {
			for(int i = 0 ;i<50;i++){
				Thread.sleep(100);
				System.out.println("当前线程是:"+Thread.currentThread().getName()+"----->>>访问非同步方法"+i);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

----------打印结果-------------
当前线程是:线程1------>>>跑到46
当前线程是:main----->>>访问非同步方法45
当前线程是:main----->>>访问非同步方法46
当前线程是:线程1------>>>跑到47
当前线程是:线程1------>>>跑到48
当前线程是:main----->>>访问非同步方法47
当前线程是:main----->>>访问非同步方法48
当前线程是:线程1------>>>跑到49
当前线程是:main----->>>访问非同步方法49

4、例子:(当一个线程访问synchronized声明的代码块时,别的线程访问其他synchronized代码块时将被堵塞):

package com.sxit.test;

public class Test implements Runnable {

	public static void main(String[] args) {

		Test test1 = new Test();
		// 启一个线程
		Thread thread1 = new Thread(test1, "线程1");
		thread1.start();
		
		try {
			//主线程先睡一会儿,让线程1先执行
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		// 当前主线程main执行test方法将被堵塞,知道线程1执行完释放当前对象锁才能执行test方法
		test1.test();
	}

	public void run() {
		// 对当前对象加锁,同一时刻只能有一个线程持有当前对象的锁,一定要等第一个线程执行完,锁释放后,第二个线程才开始跑
		synchronized (this) {
			for (int i = 0; i < 100; i++) {
				System.out.println("当前线程是:" + Thread.currentThread().getName() + "------>>>跑到" + i);
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void test() {
		synchronized (this) {
			for (int i = 0; i < 50; i++) {
				System.out.println("当前线程是:" + Thread.currentThread().getName() + "----->>>访问非同步方法" + i);
			}
		}
	}
}


---------打印信息-----------
当前线程是:线程1------>>>跑到1
当前线程是:线程1------>>>跑到2
。。。。。。。。。。。。。。。。
当前线程是:线程1------>>>跑到49
当前线程是:线程main------>>>跑到1
。。。。。。。。。。。。。。。。
当前线程是:线程main------>>>跑到49

5、Thread类中start()方法源码:

	/**
	 * Causes this thread to begin execution; the Java Virtual Machine 
	 * calls the run method of this thread. 
	 *  线程开始执行;JVM会调用该线程的run方法,也就是调用Runnable的run方法 见源码即:
	 * 	public void run() {
	 *      //target是构造器传入的Runnable对象,如果不为空,则调用它的Run方法
	 * 		if (target != null) { 
	 * 			target.run();
	 *  	}
	 *  }
	 * 
	 * The result is that two threads are running concurrently: the 
	 * current thread (which returns from the call to the 
	 * start method) and the other thread (which executes its 
	 * run method). 
	 * 
	 * It is never legal to start a thread more than once.
	 * 重复调用start方法启动线程是非法的
	 * In particular, a thread may not be restarted once it has completed
	 * execution.
	 * 如果线程已经执行完毕,不能再重复启动了
	 * 见源码started标示
	 *
	 * @exception  IllegalThreadStateException  if the thread was already
	 *               started.
	 */
	//synchronized关键字修饰,防止同一时刻有多个线程一起启动
	public synchronized void start() {
		if (started)
			throw new IllegalThreadStateException();
		//如果已经启动了,则started标示为true,下一次启动直接抛出异常
		started = true;
		//将当前线程加入到线程组中
		group.add(this);
		start0();
	}

	// native方法里执行 闭源无法看到
	private native void start0();

	public void run() {
		if (target != null) {
			target.run();
		}
	}

6、小结:

1)、每个类实例都对应一把锁,如果你要访问该对象的synchronized方法,你就首先得先获得这把锁,否则所属线程阻塞,方法一旦执行,就独占此锁,知道方法返回后才将锁释放,被阻塞的线程也就可以去争取这个锁了。

  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值