Java线程知识点

来源:互联网 发布:sql注入防御方法 编辑:程序博客网 时间:2024/06/01 14:45

1.什么是原子操作:

原子操作就是计算机在执行指令过程中不可分割的最小指令单元,不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行倒结束,中间不会有任何context switch(切换到另一个线程)。比如声明变量的操作、非long和double型的primitive进行赋值,以及返回这两者之外的primitive,这些都是原子操作,这些操作是安全的,注意++, --操作不是原子操作;有些文章中强调:在多线程的程序中,一旦将某个关键代码封装成一个原子操作,那么对它们的操作就不会存在不同步的情况。个人不太认可这种看法,看如下代码:

这里的setter方法只有赋值操作,是原子操作,假设有如下的情景:num的初始值为0,线程A调用setNum(5)方法中,然后线程B调用setNum(10),然后线程A调用getNum得到的值是5而不是10,这是因为线程A得到的是是从其私有内存中(什么是私有内存,请看第2点)返回的;解决问题的方法:(1)将num的声明改为private volatile int num; (2)在getter和setter方法前加关键字synchronized.

后记:似乎这种情景不会存在,因为一般是通过Counter的实例去调用setNum方法,如果一个线程更改了num值,则是通过Counter的实例进行更改的,只要两个线程共享的是同一个Counter,那么结果还是同步的,所以不需要volatile和synchronized,看如下的代码:

打印出的结果是10;

2.什么是私有内存,什么是共享内存(下面是个人的理解):

根据Java Language Specification中的说明, jvm系统中存在一个主内存(Main Memory或Java Heap Memory),Java中所有变量都储存在主存中,对于所有线程都是共享的。

每条线程都有自己的工作内存(Working Memory),也就是私有内存,此工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。

3.为什么++,--不是原子操作(最好通过发编译过程看执行步骤

以n++为例,操作方式是先取出n的值,然后对其加1,再赋给n,这里牵涉到读和写两步操作,所以不是原子操作;

4.同步方法锁定的是什么对象:

(1)实例方法使用的锁是当前的对象,当线程进入当前对象的方法并获取当前对象为锁,其他的前程就不能在获取到此对象锁,执行对象的任意一个同步方法;如下代码:

 

等同于:

  

(2)静态方法使用的锁是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了),如:

 

和如下代码相同的作用,两者获取相同的锁:

 

原创粉丝点击