线程状态 jdk中线程状态分为:new,runnable,blocked,waiting,timed_waiting,dead.其中new为刚创建还没有开始执行的状态,
而runnable状态分为可以执行和正在执行,可以执行是因为可能要等cpu时间片等。blocked状态是指线程在阻塞等待监视器的锁。waiting是指执行了Object.wait(),Thread.join()等方法进入waiting状态;timed_waiting是指带时间数的waiting状态,在时间到达之前都是在waiting状态,dead状态是指结束任务的线程状态,再也不能回到runnable状态了。
在线程中有waiting set和ready set概念。
当一个对象执行Object.wait()/Object.join(),该线程进入waiting set,同时需要释放监视器的锁。监视器也是一个普通对象,在加上一些关键语法后,就能成为监视器。
当一个对象执行Object.notify()时,是在waiting set选择一个thread进入ready set,当这个thread能获得这个监视器的锁时候,就可以进入runnable状态,否则就待在ready set,notifyAll()是通知waiting set里面的所有线程,然后选择其中的一个,不确定是哪一个,线程的优先级也只是一个提示和指导。
Object.wait(time)/Object.join(time)方法这些都是在时间限制到达之前thread在waiting set,时间到期之后自动进入ready set。
Thread.sleep()/Thread.yield()执行时thread都不会放弃监视器的锁,只是进入ready set,Thread.sleep()只是在指定的时间内休眠,得不到任何的资源.Thread.yield()只是提示thread工作差不多完成了,可以让步给其他Thread,这个让步不保证完成,这个也只对同等级的线程有效。
监视器 java使用监视器来表示同步锁,在Java里面,任何一个Object Reference都可以作为同步锁,只要使用synchronized:
public static final Object signal = new Object();
f1(){
synchronized(signal){
}
}
在jvm内部synchronized会被表示成monitorenter和monitorexit;在一个时间段,只有一个线程能持有monitor,也就是在monitorenter里面,也就达到了同步的目的.当想获得一个类变量锁的时候,可以使用这个类的class类。
内存模型在jvm规范中规定java内存模型是java thread work memory和java main memory两部分
每个thread一个thread memory,初始为空,必要时和main memory通信
规范规定了工作内存和主内存之间通信的8个行为:
use, assign, load, store,read,write, lock, and unlockuse:使用一个线程工作内存中的变量,看成线程的行为
assign:设置一个线程工作内存中的变量,设置的值来自线程执行引擎,看成线程的行为
read:把主内存的值读到线程工作内存当中,看成主内存的行为
load:在read之后执行,真正的把值读到到工作内存当中,看成线程的行为
store:保存工作内存的值,等下在执行write后传输给主内存,看成线程的行为
write:在store后执行,看成主内存的行为
lock和unlock是获取监视器锁和释放锁的行为,是第三方synchronized行为
这样的内存模型就会有问题:
线程工作内存是独立的,在工作内存A的变量被工作内存B看到需要经过A-->主内存-->B的程度,那么什么时候进行工作内存到主内存的通信呢?
这里需要涉及到
缓存一致性模型,即工作内存(缓存)什么时候刷新和读取主内存必须遵循一定的规则才可以。
java使用释放一致性模型:在释放锁的时候写入主内存
也就是当synchronized表示的方法或者运行块执行结束时监视器锁释放后,里面涉及的所有变量(局部变量除外)的值都写入了主内存,当变量被其他线程看到的话,其值是最新的。
那么方法或运行块未进行同步,可能有两方面的问题:
1.方法的执行顺序是未定的
2.即使方法的执行顺序是相同的,由于工作内存的值未写到主内存中也有可能有问题
thread在jvm当中执行的顺序和代码中看到的顺序可能是不一样的,为了性能优化等代码可能进行重排序,所有jmm定义了
线程的执行顺序模型:happens-before模型,规则如下:
1.一个线程当中,先出现的指令happens-before后出现的指令
2.构造器的里面指令happens-before创建对象的指令
3.对于一个监视器,unlock happens-before 想去得锁的指令
4.对于volatile的变量,write happens-before read
5.A call to start() on a thread happens-before any actions in the started thread.
6.All actions in a thread happen-before any other thread successfully returns from a
join() on that thread.
happens-before模型保证了JMM内存模型的访问方式。
对于synchronized我们可以认为他符合了上面的第3点
对于volatile变量,保证了在线程每次修改后马上反映到主内存当中,也就是可见性。
1.All instance fields, static fields and array elements are stored in heap memory.存放在java堆内
2.