Java面试题(一)

1.乐观锁和悲观锁的具体实现

乐观锁

总是认为不会产生并发问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS操作实现。

version方式实现乐观锁

一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值加1,。当线程A要更新数据值时,在读取数据同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。

核心SQL代码:

update table set x=x+1, version=version+1 where id=#{id} and version=#{version};

CAS操作方式

即compare and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作。

悲观锁

总是假设最坏的情况,每次取数据都认为其他线程会修改,所以都会加锁(读锁、写锁、行锁等),当其他线程想要访问数据时,都需要阻塞挂起。可以依靠数据库实现,如行锁、读锁、和写锁等、都是在操作之前加锁,在java中,synchronize的思想也是悲观锁。

final修饰的对象初始化时分两种情况

一,修饰成员对象时有三种初始化方式

1.在定义变量时直接赋值
2.声明完变量后在构造方法中为其赋值
3.声明完变量后在构造代码块中为其赋值

二、修饰类对象有两种方式(静态对象)

1.在定义类变量时直接赋值
2.在静态代码块中赋值

public class TestFinal {

//    一、使用Final修饰符修饰的类的特点:该类不能有子类;
//
//    二、使用Final修饰符修饰的对象的特点:该对象的引用地址不能改变;
//
//    三、使用Final修饰符修饰的方法的特点:该方法不能被重写;
//
//    四、使用Final修饰符修饰的变量的特点:该变量会变成常亮,值不能被改变。

//-----------------成员变量------------------//
//初始化方式一,在定义变量时直接赋值
private final int i = 5;
private final SysUser sysUser = new SysUser();
private final Book book = new Book();

//初始化方式二,声明完变量后在构造方法中为其赋值
//如果采用用这种方式,那么每个构造方法中都要有j赋值的语句
private final int j;
private final Book book1;

public TestFinal() {
    j = 5;
    book1=new Book("三国演义","罗贯中");
//        book=book1;
//        book.setName("111");
//        book.setAuthor("2222");
}

//如果取消该构造方法的注释,程序就会报错,因为它没有为j和book1赋值
/*public TestFinal(String str) {

}*/
public TestFinal(String str) {
    // 为了方便我们可以这样写
    this();
}


//下面的代码同样会报错,因为对j重复赋值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值