Java中的关键字

编写程序时,需要给类,方法或变量等起名字,这些就是标识符,在Java中有的表示符被赋予了特殊的含义,这些特殊含义的标识符就是关键字。

1.Default

default关键字比较特殊,既可以用于程序控制,也可以用于修饰接接口类。

在switch中,当匹配不到case语句时,会默认执行defalut中的语句。
在原来的接口中,接口默认是public abstract修饰的,是不可以有方法体的
但java8后,default修饰的方法可以拥有方法体,实现类可以重写也可以不重写该方法
实现类如果重写了该方法,则执行重写后的方法。

public interface Default {
 
    default  void method(){
        System.out.println("method in interface");
    }
}

2.Native

简单来说,Native关键字所修饰的方法就是调用一个非java的方法,因为JVM是运行在数据库之上,需要和底层操作系统打交道,通过调用本地方法可以实现与底层系统打交道。注意类中定义的Native方法不需要方法体。

当调用native 方法时,程序会进入本地方法栈,通过本地方法接口(JNI)调用本地方法库,比较典型的就是Java线程中的start0();已经hashCode()获取哈希值的方法

  

3.synchronized

针对java并发中资源共享的问题,引入关键字加锁,Jdk1.5以前属于重量锁,因为1.5以前需要依赖底层的Lock来实现,线程之间的切换需要操作系统在内核态和用户态之间切换,这个过程比较消耗时间。

synchronized主要作用有:(1) 原子性:原子性是指一个或者一组操作要么都执行,要么都不执行,执行过程中不会被任何因素打断 (2)可见性:指多线程访问一个资源时,该资源的信息对于其他线程来说是可见的 (3)有序性:指程序执行的顺序按照代码先后执行,synchronized保证了每个时刻只有一个线程可以访问到这个资源。

//(1)修饰实例方法: 作用于当前对象实例加锁,进入同步代码前要获得当前对象实例的锁
synchronized void method() {
  //业务代码
}
/**(2)修饰静态方法: 也就是给当前类加锁,会作用于类的所有对象实例 ,进入同步代码前要获得 当前 class 的锁。因为静态成员不属于任何一个实例对象,是类成员。所以,如果一个线程 A 调用一个实例对象的非静态 synchronized 方法,而线程 B 需要调用这个实例对象所属类的静态 synchronized 方法,是允许的,不会发生互斥现象,因为访问静态 synchronized 方法占用的锁是当前类的锁,而访问非静态 synchronized 方法占用的锁是当前实例对象锁。**/

synchronized void static method() {
  //业务代码
}

/**(3)修饰代码块: 指定加锁对象,对给定对象/类加锁。synchronized(this|object) 表示进入同步代码库前要获得给定对象的锁。synchronized(类.class)表示进入同步代码前要获得当前 class 的锁**/

synchronized(this) {
  //业务代码
}

4.Volatile

在双重检测的单例模式中,会出现一个问题,比如A线程拿到了创建单例的锁开始new对象,但是new对象分为分配内存空间、执行构造方法、对象指向内存空间,jvm优化机制导致指令可能会重排,比如先执行1和3步,这时候如果有一个线程B判断单例不为null,就会直接拿去用,但是此时这个实例对象是没有初始化的,只是一片空的内存空间。

    1.内存可见性:可见性与Java的内存模型有关,模型采用缓存与主存的方式对变量进行操作,也就是说,每个线程都有自己的缓存空间,对变量的操作都是在缓存中进行的,之后再将修改后的值返回到主存中,这就带来了问题,有可能一个线程在将共享变量修改后,还没有来的及将缓存中的变量返回给主存中,另外一个线程就对共享变量进行修改,那么这个线程拿到的值是主存中未被修改的值,这就是可见性的问题。volatile很好的保证了变量的可见性,当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值,这就保证了可见性。

    2.原子性:volatile不保证原子性,在java中很多操作不是原子性的,比如自增操作,就分为拿到值,修改 再写会回去三步。

例如
线程A首先得到了i的初始值100,但是还没来得及修改,就阻塞了,这时线程B开始了,它也得到了i的值,由于i的值未被修改,即使是被volatile修饰,主存的变量还没变化,那么线程B得到的值也是100,之后对其进行加1操作,得到101后,将新值写入到缓存中,再刷入主存中。根据可见性的原则,这个主存的值可以被其他线程可见。
问题来了,线程A已经读取到了i的值为100,也就是说读取的这个原子操作已经结束了,所以这个可见性来的有点晚,线程A阻塞结束后,继续将100这个值加1,得到101,再将值写到缓存,最后刷入主存,所以即便是volatile具有可见性,也不能保证对它修饰的变量具有原子性。
 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值