8.4 线程同步

目录

对象锁使用说明:

1.返回对象的锁

2.共享数据的所有访问都必须作为临界区,使用synchronized加锁

3.synchronized保护的共享数据必须是私有的

4.如果一个方法的整个方法都在synchronized中,则可以把关键字放在函数声明中

5.对象锁具有可重入性

死锁的防治

线程之间的交互:wait() , notify()

线程运行状态

支持线程的类

Thread

Runnable           

Object类

ThreadGroup类

ThreadDeath类   

线程组 

Thread类其他的方法


Java中对共享数据操作的并发控制采用了传统的锁技术。

一个程序中单独的、并发的线程对同一对象进行访问的代码段被称为临界区。

使用synchronized关键字标识,临界区可以是一个语句块,或方法。

synchronized (object) 被称为对象锁,给object对象上锁。是独占排它锁,其他线程不能对该对象操作。

对象锁使用说明:

1.返回对象的锁

对象的锁在如下几种情况下由持有线程返还

  • synchronized()语句执行完毕
  • synchronized()语句中出现异常
  • 当持有锁的线程调用该对象的wait()方法,释放对象锁,被放入对象的wait pool

2.共享数据的所有访问都必须作为临界区,使用synchronized加锁

3.synchronized保护的共享数据必须是私有的

4.如果一个方法的整个方法都在synchronized中,则可以把关键字放在函数声明中

5.对象锁具有可重入性


死锁的防治

多个线程相互等待对方持有的锁,但是对方的锁都不释放,就造成了死锁。

获取锁的顺序 需要全局考虑,释放锁的顺序和加锁顺序相反。


线程之间的交互:wait() , notify()

 线程中调用了某对象的X.wai() ,该线程将被放入X的wait pool中,该线程将释放X的锁;

当调用X.notify() X中的wait pool中一个线程将被移入lock pool,并等待X的锁;

notifyAll() 把X的wait pool中的所有线程都放入lock pool;

临界区代码

import java.util.Vector;
public class SyncStack {
    private Vector buffer = new Vector(400,200);
    public synchronized char pop(){
        char c;
        while(buffer.size()==0){
            try{
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        c = ((Character) buffer.remove(buffer.size() - 1)).charValue();
        return c;
    }
    public synchronized void push(char c){
        this.notify();
        Character charObj = new Character(c);
        buffer.addElement(charObj);
    }
}

不建议使用:

stop :强制终止进程,容易造成数据不一致

suspend() 和resum():suspend暂停线程但是不会释放锁,容易造成死锁。


线程运行状态

新建、可运行状态(就绪)、运行、阻塞(等待)、结束。

  • 新建: 使用Thread类或其子类创建的线程,还未分配相关资源,只能使用start 和stop 方法;
  • 可运行状态:使用start方法后,将线程由新建变为可运行太,并分配资源,等待调度;
  • 运行态:线程占用CPU执行,状态变迁由三种:
  •                 1. 正常执行后到结束
  •                 2.被高优先级抢占式夺取CPU,或者时间片使用完而进入就绪(Runnable);
  •                 3.进入阻塞态
  •                         线程调用了sleep(),join(),wait()方法
  •                         使用synchronized 来请求对象的锁而为获得时
  •                         线程中由输入输出操作
  • 阻塞状态(block):
  •                 sleep() join() 是等待阻塞
  •                 wait(), notify(),notifyAll(),synchronized 唤醒,被中断interrupt或等待时间到,是对象锁阻塞
  • 终止状态(Dead)

                


支持线程的类

均在lang包下

Thread

thread 的子类实现run() {} 方法中的线程体

Runnable           

实现了Runnable接口的类中的run方法提供线程体

Object类

wait(), notify(),notifyAll()  

ThreadGroup类

ThreadDeath类   

 


线程组 

package Thread03;

public class TestMain {
    public static void main(String[] args) {
        ThreadGroup mySchool = new ThreadGroup("mySchool");
        Thread t1 = new Thread(mySchool, new Sing());
        Thread t2 = new Thread(mySchool, new Dance());
        System.out.println("唱歌线程组:" + t1.getThreadGroup());
        System.out.println("跳舞线程组:" + t2.getThreadGroup());
        t1.start();
        t2.start();
        t1.setName("唱歌");
        System.out.println("线程唱歌名字:" + t1.getName());
        System.out.println(t2.toString());
    }
}
class Sing extends  Thread{
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println("im sing............");
        }
    }
}

class Dance implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println("im danceing......................");
        }
    }
}

                 

Thread类其他的方法

setName() ,getName() 设置线程名,获取线程名

activeCount() 返回线程组中活动线程的个数

getThreadGroup() 获取线程组

setDaemon() 设置守护线程

isDaemon()判断是否为守护线程

toString()返回线程id,优先级,线程组

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值