有知道java学习机构荣新教育的吗?怎么样啊?

荣新教育的java学习课程有没有保障? - 知乎2被浏览3分享邀请回答0添加评论分享收藏感谢收起您现在的位置:首页>技术分享> >
 但在多线程中,上面的代码会出现严重的问题,如果线程1经判断a==b,准备执行a=c时,cpu切换到线程2,且将a改成了d,
& & 当cpu重新切换到线程1,此时a已经不等于b了,也即是执行a=c的前提条件已经不满足;
&因此我们需要对上面的操作原子的进行,当然我们可以对程序块加锁实现,这里我们讨论另一种实现方法,即使用Unsafe类CAS方法
Unsafe类?
这是sun.misc包中一个类,这并不是一个正常的类,没有办法使用正常的new Unsafe()来创建对象,其虽然提供了静态的getUnsafe方法,但仍然无法使用,调用时会报java.lang.SecurityException: Unsafe的错误。当然我们可以通过反射去绕过限制,但除非必要在正式项目中最好不要使用,拿来探究jvm确实是很有用的类。
private&Unsafe() {
@CallerSensitive
public&static&Unsafe getUnsafe() {
&&&&Class var0 = Reflection.getCallerClass();
&&&&if(var0.getClassLoader() !=&null) {
&&&&&&&&throw&new&SecurityException(&Unsafe&);
&&&&}&else&{
&&&&&&&&return&theU
例如:可以直接操作内存,下面三个方法分别申请内存,扩充内存及释放内存。
public&native&long&allocateMemory(long&paramLong);
public&native&long&reallocateMemory(long&paramLong1,&long&paramLong2);
public&native&void&freeMemory(long&paramLong);  
CAS方法:以compareAndSwapInt为例,var1是需要更新的变量,var2是相对object对象的偏移量(一般为var1某个整形属性的偏移量),var4是期望值,var5是整形属性的新值。
public&final&native&boolean&compareAndSwapObject(Object var1,&long&var2, Object var4, Object var5);
public&final&native&boolean&compareAndSwapInt(Object var1,&long&var2,&int&var4,&int&var5);
public&final&native&boolean&compareAndSwapLong(Object var1,&long&var2,&long&var4,&long&var6);
查看一些文章,在linux中的实现这样一个函数:*ptr 与old 相比较,如相同,则new写入ptr
cmpxchg(void&*ptr, unsigned&long&old, unsigned&long&new);
下面看一个demo,在这个例子中,我们创建了一个Unsafe实例,并通过它直接创建了一个UserToken对象,我们发现创建过程中并未进行初始化,之后测试了 compareAndSwapInt方法,当age==10时,设置age=30成功,当age!=10时(此时age=30),设置age=20失败。
import&sun.misc.U
import&java.lang.reflect.F
&* Created by liushuai on 17/5/2.
public&class&UserToken {
&&&&private&String name =&&test&;
&&&&private&int&age =12;
&&&&private&UserToken(){
&&&&&&&&name =&&1234&;
&&&&&&&&age =&5;
&&&&public&static&void&main(String[] args)&throws&Exception {
&&&&&&&&Field f = Unsafe.class.getDeclaredField(&theUnsafe&);&
&&&&&&&&f.setAccessible(true);
&&&&&&&&Unsafe unsafe = (Unsafe) f.get(null);
&&&&&&&&UserToken t = (UserToken)unsafe.allocateInstance(UserToken.class);
&&&&&&&&System.out.println(t.age);&&
&&&&&&&&t.age=10;
&&&&&&&&System.out.println(t.age);&&
&&&&&&&&Field ageFiled = t.getClass().getDeclaredField(&age&);
&&&&&&&&long&offset = unsafe.objectFieldOffset(ageFiled);
&&&&&&&&boolean&flag = pareAndSwapInt(t,offset,10,30);
&&&&&&&&System.out.println(flag);
&&&&&&&&System.out.println(t.age);
&&&&&&&&flag = pareAndSwapInt(t,offset,10,20);
&&&&&&&&System.out.println(flag);
&&&&&&&&System.out.println(t.age);
AtomicInteger中CAS应用
此类位于java.util.concurrent.atomic包下,提供对整形数字的原子操作。
private&static&final&Unsafe unsafe = Unsafe.getUnsafe();
private&static&final&long&valueO
&&&&valueOffset = unsafe.objectFieldOffset
&&&&&&&&(AtomicInteger.class.getDeclaredField(&value&));
&&}&catch&(Exception ex) {&throw&new&Error(ex); }
private&volatile&int&
  从代码中我们看到,AtomicInteger类持有一个静态final修饰的Unsafe对象,并在静态块中初始化获取了此类中私有变量value的对象偏移量,value即是对象包含的真正的整形数值,由volatile关键字修饰,确保对value的修改对所有线程可见,valueOffset即value值在内存中相对于AtomicInteger实例对象的偏移量。根据上面的例子可知,可以使用unsafe根据偏移量获取和修改value的值,而且操作保证原子性。
&&&&&* Atomically sets the value to the given updated value
&&&&&* if the current value {@code ==} the expected value.
&&&&&* @param expect the expected value
&&&&&* @param update the new value
&&&&&* @return true if successful. False return indicates that
&&&&&* the actual value was not equal to the expected value.
&&&&public&final&boolean&compareAndSet(int&expect,&int&update) {
&&&&&&&&return&pareAndSwapInt(this, valueOffset, expect, update);
以及自增方法:调用链为
getAndIncrement----&compareAndSet-----&pareAndSwapInt
&&&&* Atomically increments by one the current value.
&&&&* @return the previous value
&&&public&final&int&getAndIncrement() {
&&&&&&&for&(;;) {
&&&&&&&&&&&int&current = get();
&&&&&&&&&&&int&next = current +&1;
&&&&&&&&&&&if&(compareAndSet(current, next))
&&&&&&&&&&&&&&&return&
AQS中状态的变更
AQS全称AbstractQueuedSynchronizer,位于java.util.concurrent.locks包中一个抽象类,这个类提供许多公共的方法供子类使用,其中存储了一个链式结构的双向链表队列,用来存储被阻塞的线程,并且将这部分线程封装成Node对象,并保存了线程的等待状态waitStatus。
/** waitStatus value to indicate thread has cancelled */
static&final&int&CANCELLED =&&1;
/** waitStatus value to indicate successor's thread needs unparking */
static&final&int&SIGNAL&&& = -1;&
/** waitStatus value to indicate thread is waiting on condition */
static&final&int&CONDITION = -2;&
&* waitStatus value to indicate the next acquireShared should
&* unconditionally propagate
static&final&int&PROPAGATE = -3;
volatile&int&waitS
private&volatile&int&
我们暂不讨论AQS实现原理,只探究下它的状态变换机制,及Node替换。如下面我们看到的,对于waitStatus,state,head,tail,nex等变量,都使用了volatile修饰,以确保其修改对所有线程可见,初始化时获取Unsafe实例,并在static静态块中初始化获取以上变量在内存中相对于对象的偏移量。
private&static&final&Unsafe unsafe = Unsafe.getUnsafe();&&
private&static&final&long&stateO
private&static&final&long&headO
private&static&final&long&tailO
private&static&final&long&waitStatusO
private&static&final&long&nextO
static&{&&&
&&&&&&&&stateOffset = unsafe.objectFieldOffset
&&&&&&&&&&&&(AbstractQueuedSynchronizer.class.getDeclaredField(&state&));
&&&&&&&&headOffset = unsafe.objectFieldOffset
&&&&&&&&&&&&(AbstractQueuedSynchronizer.class.getDeclaredField(&head&));
&&&&&&&&tailOffset = unsafe.objectFieldOffset
&&&&&&&&&&&&(AbstractQueuedSynchronizer.class.getDeclaredField(&tail&));
&&&&&&&&waitStatusOffset = unsafe.objectFieldOffset
&&&&&&&&&&&&(Node.class.getDeclaredField(&waitStatus&));
&&&&&&&&nextOffset = unsafe.objectFieldOffset
&&&&&&&&&&&&(Node.class.getDeclaredField(&next&));
&&&&}&catch&(Exception ex) {&throw&new&Error(ex); }
&&&&&* Atomically sets synchronization state to the given updated
&&&&&* value if the current state value equals the expected value.
&&&&&* This operation has memory semantics of a &tt&volatile&/tt& read
&&&&&* and write.
&&&&&* @param expect the expected value
&&&&&* @param update the new value
&&&&&* @return true if successful. False return indicates that the actual
&&&&&*&&&&&&&& value was not equal to the expected value.
&&&&protected&final&boolean&compareAndSetState(int&expect,&int&update) {
&&&&&&&&return&pareAndSwapInt(this, stateOffset, expect, update);&
&&&&&* CAS head field. Used only by enq.
&&&&private&final&boolean&compareAndSetHead(Node update) {
&&&&&&&&return&pareAndSwapObject(this, headOffset,&null, update);&&
&&&&&* CAS tail field. Used only by enq.
&&&&private&final&boolean&compareAndSetTail(Node expect, Node update) {
&&&&&&&&return&pareAndSwapObject(this, tailOffset, expect, update);&
&&&&&* CAS waitStatus field of a node.
&&&&private&static&final&boolean&compareAndSetWaitStatus(Node node,&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&expect,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&update) {
&&&&&&&&return&pareAndSwapInt(node, waitStatusOffset,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&expect, update);
&&&&&* CAS next field of a node.
&&&&private&static&final&boolean&compareAndSetNext(Node node,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&Node expect,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&Node update) {
&&&&&&&&return&pareAndSwapObject(node, nextOffset, expect, update);
荣新科技十年沉淀提供,行业独家领先的课程,高薪就业不是梦!
Copyright & 荣新IT培训中心 - Oracle培训、Linux培训、IOS培训、WEB前端工程师培训 京ICP备
地址:北京市海淀区白石桥路方圆大厦5层 (首都体育馆东侧) / 北京市海淀区四道口京果商厦 / 中关村软件园9号楼4层java小白,去荣新教育java学习班学习如何? - 知乎2被浏览5分享邀请回答0添加评论分享收藏感谢收起有知道Linux云计算学习机构荣新教育的吗?怎么样啊? - 知乎2被浏览7分享邀请回答0添加评论分享收藏感谢收起

我要回帖

 

随机推荐