java 线程简述

sancaiodm Java 2022-02-17 1319 0

【1】线程为分工作线程与守护线程

工作线程:当线程的任务执行完或通知方式结束(也叫用户线程)

守护线程:一般是为工作线程服务的,当所有的工作线程结束,守护线程也会自动结束(垃圾回收机制就是守护线程)

守护线程创建的线程也是守护线程,守护线程不应该访问,写入持久化资源,如文件,数据库,因为它会在任何时间被停止,导致资源未释放,数据写入中断等等异常问题


【2】join方法作用:当我们调用某个线程的join方法时,这个方法(join方法)会挂起调用线程(主线程),直到被调用线程结束执行,调用线程才会继续执行(通俗说就是:线程插队)。

【3】yield方法作用:线程的礼让,让出CPU,让其他线程执行,但礼让的时间没法确定,所以也不一定礼让成功


【4】线程安全是指某方法或是代码块,在多线程中能够正确的执行,不会出现数据不一致或是数据污染的问题,我们就把这样的程序称之为线程安全,反之则为非线程安全。

java 线程竟态条件

image.png

如上,由于异线程变量chepiao不是java原子操作,出现同一变量被多个线程在同一时刻使用,但变量的值未及时更新就会出现此现象,解决方案:

这是怎么回事呢?这就是内存可见性问题。在计算机系统中,除了内存,数据还会被缓存在CPU的寄存器以及各级缓存中,当访问一个变量时,可能直接从寄存器或CPU缓存中获取,而不一定到内存中去取,当修改一个变量时,也可能是先写到缓存中,稍后才会同步更新到内存中。在单线程的程序中,这一般不是问题,但在多线程的程序中,尤其是在有多CPU的情况下,这就是严重的问题。一个线程对内存的修改,另一个线程看不到,一是修改没有及时同步到内存,二是另一个线程根本就没从内存读。

❑ 使用synchronized关键字;

❑ 使用显式锁;

❑ 使用原子变量

❑ 使用volatile关键字(轻量级的实现,成本最低,可保证变量读写到内存最新值,而非缓存的值)


Synchronized关键字:互斥锁。

Synchronized的作用:实现线程同步。

当有一个线程对内存进行操作时,其它线程都不可以对这个内存地址进行操作,直到此线程操作完成,其它线程才有机会去操作此内存地址的操作。

Synchronized的具体使用:

1 同步代码块

synchronized(对象){//得到对象的锁,此对象也就是this

   //需要被同步的逻辑代码

}

2 synchronized还可以用在方法声明中,表示此方法是为同步方法,如果此方法是实例方法(无static修饰),则默认锁对象是this,也可以是其它对象(要求是同一个对象),

//可以是其它对象,但必须是一个对象,

Object lock = new Obejct();

synchronized(lock ){

}

//如果不是同一对象,需是加锁在不同的对象,则synchronized毫无意义,

A a= new A();A b= new A();A c= new A();//不对的对象内不的对象锁

2.1如果同步方法是静态方法,则锁为当前类本身(xxx.class),每个对象都有一个锁和一个等待队列,类对象(xxx.class)也是一样

public static void androidosnet(){

    synchronized(A.class){

   }

}

synchronized修饰的方法,其在被调的过程大致如下:

1)尝试获得锁,如果能够获得锁,继续下一步,否则加入等待队列,阻塞并等待唤醒。

2)执行实例方法体代码。

3)释放锁,如果等待队列上有等待的线程,从中取一个并唤醒,如果有多个等待的线程,唤醒哪一个是不一定的,不保证公平性。

以下情况为释放锁:当前线程的同步方法或是同步代码块 

【1】执行结束,

【2】遇到return,break,

【3】同步逻辑中出现error或是Exception导致线程异常结束。

【4】执行了wait方法,使用当前线程暂停了其会释放锁。

Sleep()与yield()两方法会暂停当前线程,但不会释放锁。

【androidos.net提示:重要的事说三遍,重要的事说三遍,重要的事说三遍】

synchronized保护的是对象而非代码,只要访问的是同一个对象的synchronized方法,即使是不同的代码(方法或是代码块),也会被同步顺序访问,

示例如下

Thread one = new Thread();

Thread two= new Thread();

public synchronized void mthonA(){

}

public synchronized void mthonB(){

}

如下有两个用户线程one,two,在用户线程one中调用mthonA,在用户线程two中调用mthonB,当这两个线程one,two同步启动start,是不会在同一时刻分别这两个方法,必须是一个线程先执行完mthonA方法,另一个线程再接着执行mthonB方法


【4】对象的wait()与notify方法

评论