您的位置:首页 > 编程语言 > Java开发

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

2016-06-06 18:48 393 查看
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() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。

.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息