JAVA学习笔记--多线程(三)synchronized实现线程同步

JAVA中对同步控制主要通过synchronized关键字

wait()  notify()和notifyAll()方法


1.synchronized 的用法

每个类实例对应一把锁,每个synchronized方法都必须获得调用该方法的类实例的锁才能执行,否则发生线程阻塞

方法一旦执行,就独占锁,直到该方法返回时,才释放锁,此后被阻塞的线程才能获得该锁。


A . 声明方法时,放在范围操作符和返回值之间。

作用:表示一次只能有一个线程进入该方法,其他的线程想在此时调用这个方法,只能是排队等待

只有当当前的线程执行完该方法以后,其他的线程才能进入。


B. synchronized代码块

格式:synchronized(variable){

    code;

}

一次只能有一个线程进入该代码块


C . synchronized(object)

格式:synchronized(object o){

    code;

}

线程获得的是对象锁。对象锁会在下一篇笔记里详细学习,到时候再贴上链接

D . synchronized(Class)

synchronized的参数是类,只要线程进入,则该类中的所有操作都不能进进行,包括静态变量和静态方法。


synchronized代码块示例:


package synchronizedTest;

public class Tasks implements Runnable{
public void taskA()  {
	System.out.println(Thread.currentThread().getName()+"进入taskA");
    synchronized (this) {
    	System.out.println(Thread.currentThread().getName()+"synchronized in taskA()");
		try {
			//用sleep()模拟任务耗时
			Thread.sleep(2000);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
 }

public void taskB()  {
	System.out.println(Thread.currentThread().getName()+"进入taskB");
    synchronized (this) {
    	System.out.println(Thread.currentThread().getName()+"synchronized in taskB()");
		//用sleep()模拟任务耗时
    	try {
			Thread.sleep(2000);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
 }


@Override
public void run() {
	// TODO Auto-generated method stub
	taskA();
	taskB();
}
}


package synchronizedTest;

public class Test {
 public static void main(String [] args){
	 Runnable tasks1= new Tasks();
	 Thread th1=new Thread(tasks1);
	 Thread th2=new Thread(tasks1);
	 th1.start();
	 th2.start();
 }
}

输出结果:

Thread-0进入taskA
Thread-0synchronized in taskA()
Thread-1进入taskA
Thread-1synchronized in taskA()
Thread-0进入taskB
Thread-1进入taskB
Thread-0synchronized in taskB()
Thread-1synchronized in taskB()


这个例子想表达的意思是:

当两个并发线程访问同一个对象中的synchronized同步代码块时,一个时间内只能有一个线程得到执行,另一个线程必须等待当前线程完成后才能得到执行。然而,当一个线程访问synchronized同步代码块时,另一个线程仍然可以访问该对象的非synchronized同步代码块。这也是为什么结果中当Thread-0和Thread-1都可以打印出“进入代taskB”语句。

   wati(),notify()和 notifyAll() 


调用任意对象的wait()方法,都会导致线程阻塞,并且该对象上的锁被释放

调用任意对象的notify()方法,则会随机选择一个阻塞状态的进程,并解除该线程的阻塞状态。


注意:

1.这两个方法是每个对象都具有的,而不是只属于线程类。

2.如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,那么那个线程就会进入等待队列,该线程就已经不是current thread了。

3.调用wait()方法前的判断最好用while,而不用if;while可以实现被wakeup后thread再次作条件判断;而if则只能判断一次。

4.除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调用该对象的wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。






.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值