线程同步

  • synchronized

自动加解锁保证方法内部或代码块内部资源同时最多只能有一个线程访问

  • volatile

使被标记属性具有原子性(不可拆分)

只对基本类型 (byte、char、short、int、long、float、double、 boolean) 的赋值操作和对象的引用赋值操作有效。

i++
=> (不具有原子性)
val temp = i + 1
i = temp
  • AtomicInteger AtomicBoolean 等

存在ABA问题(当前内存的值一开始是A,被另外一个线程先改为B然后再改为A,那么当前线程访问的时候发现是A,则认为它没有被其他线程访问过,对于链表来说,存在风险)

val data = AtomicInteger(0)
// 通过比较内存中的值来判断是否改变,如果已经改变,则获取后重新比较,重复往返直至可以赋值
data.incrementAndGet() // ++i
data.getAndIncrement() // i++
  • AtomicStampedReference

解决ABA问题(维护一个int类型的标记stamp,每次更新数据后更新stamp),每次验证数据的差异时,也验证stamp是否改变。

val data = AtomicStampedReference<Int>(0, 0);
var stamp = data.stamp
data.compareAndSet(1, 2, stamp, stamp + 1)
stamp = data.stamp
data.compareAndSet(2, 1, stamp, stamp + 1)
  • Lock / ReentrantReadWriteLock

手动锁,必须手动解锁。synchronized是自动加解锁

val lock = ReentrantLock()

lock.lock()
try {

} finally {
  lock.unlock()
}
// 主要用途
// 读时都可读,写时不可读和写。
val executors = Executors.newCachedThreadPool()
val lock = ReentrantReadWriteLock()

val readLock = lock.readLock()
val writeLock = lock.writeLock()

val readRunnable = Runnable {
  for (i in 0 until 1000000) {
    readLock.withLock {
      println(x)
    }
  }
}
val writeRunnable = Runnable {
  for (i in 0 until 1000000) {
    writeLock.withLock {
      x++
    }
  }
}

executors.execute(readRunnable)
executors.execute(writeRunnable)
executors.execute(readRunnable)
executors.execute(writeRunnable)
  • 死锁
val obj1 = Any()
val obj2 = Any()

var i1 = 0
var i2 = 0

// 两个锁被一起锁住

fun test1() {
  synchronized(obj1) {
    i1 = 0
    synchronized(obj2) {
      i2 = 0
    }
  }
}

fun test2() {
  synchronized(obj2) {
    i2 = 0
    synchronized(obj1) {
      i1 = 0
    }
  }
}
  • 锁范围(monitor)
// 作用于当前类
synchronized(X::class) {
  
}
// 作用于当前对象
synchronized(this) {
  
}
@Synchronized
fun test(): Unit {

}
// 作用于obj
val obj = Any()
synchronized(obj) {
  
}


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!