avatar

正进一步

只有喜欢,才会全情投入,才会成功!!!

不关注架构设计细节的程序员不是一个好架构师

  • Home
  • Tags
  • Categories
  • Archives
  • 2018寄语
Java等号右边计算过程_i++例子

查缺补漏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

public static void main(String[] args) {
int i = 0;
int m = 0;
for (int j = 0; j < 10; j++) {
{
i=i++;
}
{ //相当于下面的代码
int temp= m;
m++;
m= temp;
}
}
System.out.println("i的最后结果"+i);
System.out.println("m的最后结果"+m);
}

结果:

1
2
i的最后结果0
m的最后结果0

Volatile作用及面试内容

引用自: https://mp.weixin.qq.com/s/bvqVBnYPdFvpQqdB_4kdUQ

volatile 能使得一个非原子操作变成原子操作吗?

一个典型的例子是在类中有一个long 类型的成员变量。如果你知道该成员变量会被多个线程访问,如计数器、价格等,你最好是将其设置为 volatile。为什么?因为 Java 中读取long 类型变量不是原子的,需要分成两步,如果一个线程正在修改该 long 变量的值,另一个线程可能只能看到该值的一半(前 32 位)。但是对一个 volatile 型的 long 或double 变量的读写是原子。

volatile 类型变量提供什么保证?

volatile 变量提供顺序和可见性保证,例如,JVM或者 JIT为了获得更好的性能会对语句重排序,但是 volatile 类型变量即使在没有同步块的情况下赋值也不会与其他语句重排序。 volatile 提供 happens-before 的保证,确保一个线程的修改能对其他线程是可见的。某些情况下,volatile 还能提供原子性,如读 64 位数据类型,像 long 和 double 都不是原子的,但 volatile 类型的 double 和 long 就是原子的。

volatile 修饰符的有过什么实践?

一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。double 和 long 都是64位宽,因此对这两种类型的读是分为两部分的,第一次读取第一个 32 位,然后再读剩下的 32 位,这个过程不是原子的,但Java 中 volatile 型的 long 或 double 变量的读写是原子的。volatile 修复符的另一个作用是提供内存屏障(memory barrier),例如在分布式框架中的应用。简单的说,就是当你写一个 volatile 变量之前,Java 内存模型会插入一个写屏障(writebarrier),读一个volatile 变量之前,会插入一个读屏障(read barrier)。意思就是说,在你写一个volatile 域时,能保证任何线程都能看到你写的值,同时,在写之前,也能保证任何数值的更新对所有线程是可见的,因为内存屏障会将其他所有写的值更新到缓存。

漫画之什么是CAS机制

转载自: https://mp.weixin.qq.com/s/f23I1kyJQoNPu6Ntrx0S6g

读后感:

Java1.6为Synchronized做了优化,增加了从偏向锁到轻量级锁再到重量级锁的过度,但是在最终转变为重量级锁之后,性能仍然较低. 这其中用到了CAS机制。

CAS优点

  • Synchronized属于悲观锁,悲观地认为程序中的并发情况严重,所以严防死守。CAS属于乐观锁,乐观地认为程序中的并发情况不那么严重,所以让线程不断去尝试更新。
  • 避免了context switch

CAS缺点

  • CPU消耗较大,不适合高并发场景(因为冲突太多,失败率高)。
  • ABA问题
  • 不能保证代码块的原子性。例如不能保证多个变量同时更新.

乐观锁转悲观锁的经典代码见:ConcurrentHashMap的size方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public int size() {
// Try a few times to get accurate count. On failure due to
// continuous async changes in table, resort to locking.
final Segment<K,V>[] segments = this.segments;
int size;
boolean overflow; // true if size overflows 32 bits
long sum; // sum of modCounts
long last = 0L; // previous sum
int retries = -1; // first iteration isn't retry
try {
for (;;) {
if (retries++ == RETRIES_BEFORE_LOCK) {
for (int j = 0; j < segments.length; ++j)
ensureSegment(j).lock(); // force creation
}
sum = 0L;
size = 0;
overflow = false;
for (int j = 0; j < segments.length; ++j) {
Segment<K,V> seg = segmentAt(segments, j);
if (seg != null) {
sum += seg.modCount;
int c = seg.count;
if (c < 0 || (size += c) < 0)
overflow = true;
}
}
if (sum == last)
break;
last = sum;
}
} finally {
if (retries > RETRIES_BEFORE_LOCK) {
for (int j = 0; j < segments.length; ++j)
segmentAt(segments, j).unlock();
}
}
return overflow ? Integer.MAX_VALUE : size;
}
Java能修改Final类型变量吗_setAccessible_true

Field的public void setAccessible(boolean flag) 说明

   * Set the {@code accessible} flag for this object to
* the indicated boolean value.  A value of {@code true} indicates that
* the reflected object should suppress Java language access
* checking when it is used.  A value of {@code false} indicates
* that the reflected object should enforce Java language access checks.

如果flag设置为true,那么就会压制java语言的访问校验。

微信勘误:try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
callMethod();
}
private static int callMethod() {
try {
System.out.println("call method");
return i();
}catch (Exception ex){

}finally {
System.out.println("finally block ");
}
return -1;
}
private static int i(){
System.out.println("i method");
return 1;
}

返回值

1
2
3
call method
i method
finally block