Java并發(fā)之JUC原子類(5)

1

今天我們來(lái)聊聊java.util.concurrent.atomic包下的原子類斯辰,所謂原子類就是具有原子/原子操作特征的類,在多個(gè)線程一起執(zhí)行的時(shí)候,一個(gè)操作一旦開(kāi)始吩坝,就不會(huì)被其它線程干擾。

Java8下原子類包括:

原子更新基本類型
  • AtomicInteger 整型原子類
  • AtomicLong 長(zhǎng)整型原子類
  • AtomicBoolean 布爾型原子類
原子更新數(shù)組
  • AtomicIntegerArray 整型數(shù)組原子類
  • AtomicLongArray 長(zhǎng)整型數(shù)組原子類
  • AtomicReferenceArray 引用類型數(shù)組原子類
原子更新引用
  • AtomicReference 引用類型原子類
  • AtomicReferenceFieldUpdater 原子更新引用類型里的字段
  • AtomicMarkableReference 原子更新帶有標(biāo)記位的引用類型
原子更新字段
  • AtomicIntegerFieldUpdater 原子更新整型字段的更新器
  • AtomicLongFieldUpdater 原子更新長(zhǎng)整型字段的更新器
  • AtomicStampedReference 原子更新帶有版本號(hào)的引用類型哑蔫。該類將整數(shù)值與引用關(guān)聯(lián)起來(lái)钉寝,可用于解決原子的更新數(shù)據(jù)和數(shù)據(jù)的版本號(hào),可以解決使用 CAS 進(jìn)行原子更新時(shí)可能出現(xiàn)的 ABA 問(wèn)題鸳址。

所謂的CASABA問(wèn)題:

ABA問(wèn)題.png

2

我們選取上述四個(gè)類型的各一個(gè)原子類進(jìn)行源碼解讀瘩蚪,了解大概原理即可。

在原子類里稿黍,都是使用Unsafe類進(jìn)行CAS操作疹瘦,大家有時(shí)間可以看看Unsafe類,雖然在Java9之后的版本被刪除了巡球,但是真的值得一看言沐。

2.1 AtomicInteger

說(shuō)簡(jiǎn)單點(diǎn),AtomicInteger就是利用底層類無(wú)限循環(huán)進(jìn)行CAS操作酣栈,直到成功為止险胰。

    /**
     *
     * @since 1.5
     * @author Doug Lea
     */
    public class AtomicInteger extends Number implements java.io.Serializable {
        private static final long serialVersionUID = 6214790243416807050L;
    
        // 使用Unsafe.compareAndSwapInt進(jìn)行CAS更新操作
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        // 值偏移量
        private static final long valueOffset;
    
        /*
        靜態(tài)塊初始化值偏移量
         */
        static {
            try {
                valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
            } catch (Exception ex) { throw new Error(ex); }
        }
    
        // 使用volatile修飾value 可以保證可見(jiàn)性和防止指令重排
        private volatile int value;
    
        /**
         * 有參構(gòu)造,設(shè)置value = initialValue
         */
        public AtomicInteger(int initialValue) {
            value = initialValue;
        }
    
        /**
         * 空構(gòu)造矿筝,value = 0
         */
        public AtomicInteger() {}
    
        /**
         * 獲取當(dāng)前的value
         */
        public final int get() {
            return value;
        }
    
        /**
         * 設(shè)置value值
         */
        public final void set(int newValue) {
            value = newValue;
        }
    
        /**
         * 惰性設(shè)置value值
         * unsafe.putOrderedInt() 不保證值的改變立即被其他線程看到
         * 而lazySet()的用法就是在不需要讓共享變量的修改立刻讓其他線程可見(jiàn)的時(shí)候起便,以設(shè)置普通變量的方式來(lái)修改共享狀態(tài),可以減少不必要的內(nèi)存屏障窖维,從而提高程序執(zhí)行的效率榆综。
         */
        public final void lazySet(int newValue) {
            unsafe.putOrderedInt(this, valueOffset, newValue);
        }
    
        /**
         * 原子性的設(shè)置新值并返回舊值
         */
        public final int getAndSet(int newValue) {
            return unsafe.getAndSetInt(this, valueOffset, newValue);
        }
    
        /**
         * 如果當(dāng)前值等于expect(預(yù)期值),則原子性地將該值設(shè)置為給定的update(更新值)铸史。
         */
        public final boolean compareAndSet(int expect, int update) {
            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }
    
        /**
         * 如果當(dāng)前值等于expect(預(yù)期值)鼻疮,則原子性地將該值設(shè)置為給定的update(更新值)。
         * 和上面的方法只是語(yǔ)義不同
         * weakCompareAndSet無(wú)法保證處理操作目標(biāo)的volatile變量外的其他變量的執(zhí)行順序( 編譯器和處理器為了優(yōu)化程序性能而對(duì)指令序列進(jìn)行重新排序 )琳轿,同時(shí)也無(wú)法保證這些變量的可見(jiàn)性判沟。
         */
        public final boolean weakCompareAndSet(int expect, int update) {
            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }
    
        /**
         * 原子性地將當(dāng)前值加1,并返回舊值
         */
        public final int getAndIncrement() {
            return unsafe.getAndAddInt(this, valueOffset, 1);
        }
    
        /**
         * 原子性地將當(dāng)前值減1崭篡,并返回舊值
         */
        public final int getAndDecrement() {
            return unsafe.getAndAddInt(this, valueOffset, -1);
        }
    
        /**
         * 原子性地將當(dāng)前值加delta挪哄,并返回舊值
         */
        public final int getAndAdd(int delta) {
            return unsafe.getAndAddInt(this, valueOffset, delta);
        }
    
        /**
         * 原子性地將當(dāng)前值加1,并返回新值
         */
        public final int incrementAndGet() {
            return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
        }
    
        /**
         * 原子性地將當(dāng)前值減1媚送,并返回新值
         */
        public final int decrementAndGet() {
            return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
        }
    
        /**
         * 原子性地將當(dāng)前值加delta中燥,并返回新值
         */
        public final int addAndGet(int delta) {
            return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
        }
    
        /**
         * 原子性地用給定函數(shù)的結(jié)果更新當(dāng)前值,并返回舊值塘偎。
         */
        public final int getAndUpdate(IntUnaryOperator updateFunction) {
            int prev, next;
            do {
                prev = get();
                next = updateFunction.applyAsInt(prev);
            } while (!compareAndSet(prev, next));
            return prev;
        }
    
        /**
         * 原子性地用給定函數(shù)的結(jié)果更新當(dāng)前值疗涉,并返回新值拿霉。
         */
        public final int updateAndGet(IntUnaryOperator updateFunction) {
            int prev, next;
            do {
                prev = get();
                next = updateFunction.applyAsInt(prev);
            } while (!compareAndSet(prev, next));
            return next;
        }
    
        /**
         * 原子性地用給定函數(shù)的結(jié)果更新當(dāng)前值,并返回舊值咱扣。
         *
         * IntBinaryOperator函數(shù)式接口:
         *
         * AtomicInteger.getAndAccumulate(3, (i, j) -> {
         *   // 通過(guò)給定的函數(shù)绽淘,返回要設(shè)置的結(jié)果
         *   return i * 10 * j
         * });
         * i是value
         * j是3
         */
        public final int getAndAccumulate(int x, IntBinaryOperator accumulatorFunction) {
            int prev, next;
            do {
                prev = get();
                next = accumulatorFunction.applyAsInt(prev, x);
            } while (!compareAndSet(prev, next));
            return prev;
        }
    
        /**
         * 原子性地用給定函數(shù)的結(jié)果更新當(dāng)前值,并返回新值闹伪。
         *
         * IntBinaryOperator函數(shù)式接口:
         *
         * AtomicInteger.getAndAccumulate(3, (i, j) -> {
         *   // 通過(guò)給定的函數(shù)沪铭,返回要設(shè)置的結(jié)果
         *   return i * 10 * j
         * });
         * i是value
         * j是3
         */
        public final int accumulateAndGet(int x, IntBinaryOperator accumulatorFunction) {
            int prev, next;
            do {
                prev = get();
                next = accumulatorFunction.applyAsInt(prev, x);
            } while (!compareAndSet(prev, next));
            return next;
        }
    
        /**
         * Returns the String representation of the current value.
         * @return the String representation of the current value
         */
        public String toString() {
            return Integer.toString(get());
        }
    
        /**
         * 繼承自抽象類Number后,實(shí)現(xiàn)的抽象方法
         */
        public int intValue() {
            return get();
        }
    
        /**
         * 繼承自抽象類Number后偏瓤,實(shí)現(xiàn)的抽象方法
         */
        public long longValue() {
            return (long)get();
        }
    
        /**
         * 繼承自抽象類Number后杀怠,實(shí)現(xiàn)的抽象方法
         */
        public float floatValue() {
            return (float)get();
        }
    
        /**
         * 繼承自抽象類Number后,實(shí)現(xiàn)的抽象方法
         */
        public double doubleValue() {
            return (double)get();
        }
    
    }

2.2 AtomicIntegerArray

原子性的更新數(shù)組里的某個(gè)元素厅克。

里面有幾段代碼寫(xiě)的很有意思赔退,值得玩味。

    /**
     * 整型數(shù)組元素原子性更新器
     * @since 1.5
     * @author Doug Lea
     */
    public class AtomicIntegerArray implements java.io.Serializable {
        private static final long serialVersionUID = 2862133569453604235L;
    
        // 使用Unsafe類進(jìn)行CAS操作
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        // unsafe.arrayBaseOffset() 獲取數(shù)組第一個(gè)元素的偏移地址
        private static final int base = unsafe.arrayBaseOffset(int[].class);
        // 該類型的字節(jié)位移數(shù)
        private static final int shift;
        // 數(shù)組值
        private final int[] array;
    
        // 靜態(tài)塊
        static {
            // 獲取數(shù)組中元素的增量地址
            int scale = unsafe.arrayIndexScale(int[].class);
            // 按位與操作后 比較是否等于0证舟,如果不等于0硕旗,則拋出異常
            if ((scale & (scale - 1)) != 0)
                throw new Error("data type scale not a power of two");
            // 就不在這里解釋這段代碼的含義了,觸及到了底層女责,有機(jī)會(huì)寫(xiě)一篇文章
            shift = 31 - Integer.numberOfLeadingZeros(scale);
        }
    
        // 檢查字節(jié)偏移量
        private long checkedByteOffset(int i) {
            // 快速判斷漆枚,如果
            if (i < 0 || i >= array.length)
                throw new IndexOutOfBoundsException("index " + i);
    
            // 返回字節(jié)偏移量
            return byteOffset(i);
        }
    
        private static long byteOffset(int i) {
            return ((long) i << shift) + base;
        }
    
        /**
         * 有參構(gòu)造函數(shù),參數(shù)為數(shù)組長(zhǎng)度
         * 并對(duì)array進(jìn)行初始化操作
         */
        public AtomicIntegerArray(int length) {
            array = new int[length];
        }
    
        /**
         * 有參構(gòu)造函數(shù)抵知,參數(shù)為數(shù)組
         * 并對(duì)參數(shù)array進(jìn)行克隆墙基,然后賦值給array
         */
        public AtomicIntegerArray(int[] array) {
            // Visibility guaranteed by final field guarantees
            this.array = array.clone();
        }
    
        /**
         * 返回?cái)?shù)組長(zhǎng)度
         */
        public final int length() {
            return array.length;
        }
    
        /**
         * 獲取數(shù)組指定下標(biāo)的元素
         */
        public final int get(int i) {
            return getRaw(checkedByteOffset(i));
        }
    
        /**
         * 私有方法
         * 通過(guò)偏移量獲取數(shù)組元素
         */
        private int getRaw(long offset) {
            return unsafe.getIntVolatile(array, offset);
        }
    
        /**
         * 設(shè)置數(shù)組指定下標(biāo)元素值
         */
        public final void set(int i, int newValue) {
            unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
        }
    
        /**
         * 延遲設(shè)置數(shù)組指定下標(biāo)元素值
         */
        public final void lazySet(int i, int newValue) {
            unsafe.putOrderedInt(array, checkedByteOffset(i), newValue);
        }
    
        /**
         * 原子性的設(shè)置數(shù)組指定元素值并返回舊值
         */
        public final int getAndSet(int i, int newValue) {
            return unsafe.getAndSetInt(array, checkedByteOffset(i), newValue);
        }
    
        /**
         * 進(jìn)行CAS操作設(shè)置數(shù)組指定下標(biāo)元素值
         */
        public final boolean compareAndSet(int i, int expect, int update) {
            return compareAndSetRaw(checkedByteOffset(i), expect, update);
        }
    
        private boolean compareAndSetRaw(long offset, int expect, int update) {
            return unsafe.compareAndSwapInt(array, offset, expect, update);
        }
    
        /**
         * 進(jìn)行CAS操作設(shè)置數(shù)組指定元素值
         * 和上面的方法只是語(yǔ)義不同
         * weakCompareAndSet無(wú)法保證處理操作目標(biāo)的volatile變量外的其他變量的執(zhí)行順序( 編譯器和處理器為了優(yōu)化程序性能而對(duì)指令序列進(jìn)行重新排序 ),同時(shí)也無(wú)法保證這些變量的可見(jiàn)性刷喜。
         */
        public final boolean weakCompareAndSet(int i, int expect, int update) {
            return compareAndSet(i, expect, update);
        }
    
        /**
         * 原子性的對(duì)數(shù)組指定下標(biāo)的元素值加1碘橘,并返回舊值
         */
        public final int getAndIncrement(int i) {
            return getAndAdd(i, 1);
        }
    
        /**
         * 原子性的對(duì)數(shù)組指定下標(biāo)的元素值減1,并返回舊值
         */
        public final int getAndDecrement(int i) {
            return getAndAdd(i, -1);
        }
    
        /**
         * 原子性的對(duì)數(shù)組指定下標(biāo)的元素值加delta吱肌,并返回舊值
         */
        public final int getAndAdd(int i, int delta) {
            return unsafe.getAndAddInt(array, checkedByteOffset(i), delta);
        }
    
        /**
         * 原子性的對(duì)數(shù)組指定下標(biāo)的元素值加1,并返回新值
         */
        public final int incrementAndGet(int i) {
            return getAndAdd(i, 1) + 1;
        }
    
        /**
         * 原子性的對(duì)數(shù)組指定下標(biāo)的元素值減1仰禽,并返回新值
         */
        public final int decrementAndGet(int i) {
            return getAndAdd(i, -1) - 1;
        }
    
        /**
         * 原子性的對(duì)數(shù)組指定下標(biāo)的元素值加delta氮墨,并返回新值
         */
        public final int addAndGet(int i, int delta) {
            return getAndAdd(i, delta) + delta;
        }

        /**
         * 原子性地用給定函數(shù)的結(jié)果更新數(shù)組指定下標(biāo)的元素值,并返回舊值吐葵。
         */
        public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
            long offset = checkedByteOffset(i);
            int prev, next;
            do {
                prev = getRaw(offset);
                next = updateFunction.applyAsInt(prev);
            } while (!compareAndSetRaw(offset, prev, next));
            return prev;
        }
    
        /**
         * 原子性地用給定函數(shù)的結(jié)果更新數(shù)組指定下標(biāo)的元素值规揪,并返回新值。
         */
        public final int updateAndGet(int i, IntUnaryOperator updateFunction) {
            long offset = checkedByteOffset(i);
            int prev, next;
            do {
                prev = getRaw(offset);
                next = updateFunction.applyAsInt(prev);
            } while (!compareAndSetRaw(offset, prev, next));
            return next;
        }
    
        /**
         * 原子性地用給定函數(shù)的結(jié)果更新當(dāng)前值温峭,并返回舊值猛铅。
         * 
         * IntBinaryOperator函數(shù)式接口:
         * 
         * atomicIntegerArray.getAndAccumulate(0, 3, (i, j) -> {
         *     log.info("i:" + i);
         *     log.info("j:" + j);
         *     return i + j;
         * });
         * i: 數(shù)組對(duì)應(yīng)下標(biāo)的元素值
         * j: 3
         */
        public final int getAndAccumulate(int i, int x, IntBinaryOperator accumulatorFunction) {
            long offset = checkedByteOffset(i);
            int prev, next;
            do {
                prev = getRaw(offset);
                next = accumulatorFunction.applyAsInt(prev, x);
            } while (!compareAndSetRaw(offset, prev, next));
            return prev;
        }
    
        /**
         * 原子性地用給定函數(shù)的結(jié)果更新當(dāng)前值,并返回新值凤藏。
         *
         * IntBinaryOperator函數(shù)式接口:
         *
         * atomicIntegerArray.getAndAccumulate(0, 3, (i, j) -> {
         *     log.info("i:" + i);
         *     log.info("j:" + j);
         *     return i + j;
         * });
         * i: 數(shù)組對(duì)應(yīng)下標(biāo)的元素值
         * j: 3
         */
        public final int accumulateAndGet(int i, int x, IntBinaryOperator accumulatorFunction) {
            long offset = checkedByteOffset(i);
            int prev, next;
            do {
                prev = getRaw(offset);
                next = accumulatorFunction.applyAsInt(prev, x);
            } while (!compareAndSetRaw(offset, prev, next));
            return next;
        }
    
        /**
         * Returns the String representation of the current values of array.
         * @return the String representation of the current values of array
         */
        public String toString() {
            int iMax = array.length - 1;
            if (iMax == -1)
                return "[]";
    
            StringBuilder b = new StringBuilder();
            b.append('[');
            for (int i = 0; ; i++) {
                b.append(getRaw(byteOffset(i)));
                if (i == iMax)
                    return b.append(']').toString();
                b.append(',').append(' ');
            }
        }
    
    }

2.3 AtomicReference

原子更新引用類型

    /**
     * 原子更新引用類型
     * @since 1.5
     * @author Doug Lea
     * @param <V> The type of object referred to by this reference
     */
    public class AtomicReference<V> implements java.io.Serializable {
        private static final long serialVersionUID = -1848883965231344442L;
    
        // 使用Unsafe類進(jìn)行CAS操作
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        // 值偏移地址
        private static final long valueOffset;
    
        // 靜態(tài)塊
        static {
            try {
                // 計(jì)算值的偏移地址
                valueOffset = unsafe.objectFieldOffset(AtomicReference.class.getDeclaredField("value"));
            } catch (Exception ex) { throw new Error(ex); }
        }
    
        // 值奸忽,也就是我們要操作的值
        private volatile V value;
    
        /**
         * 有參構(gòu)造
         */
        public AtomicReference(V initialValue) {
            value = initialValue;
        }
    
        /**
         * 無(wú)參構(gòu)造
         */
        public AtomicReference() {}
    
        /**
         * 獲取當(dāng)前值
         */
        public final V get() {
            return value;
        }
    
        /**
         * 設(shè)置值
         */
        public final void set(V newValue) {
            value = newValue;
        }
    
        /**
         * 惰性設(shè)置value值
         */
        public final void lazySet(V newValue) {
            unsafe.putOrderedObject(this, valueOffset, newValue);
        }
    
        /**
         * 如果當(dāng)前值等于expect(預(yù)期值)堕伪,則原子性地將該值設(shè)置為給定的update(更新值)。
         */
        public final boolean compareAndSet(V expect, V update) {
            return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
        }
    
        /**
         * 如果當(dāng)前值等于expect(預(yù)期值)栗菜,則原子性地將該值設(shè)置為給定的update(更新值)欠雌。
         * 和上面的方法只是語(yǔ)義不同
         * weakCompareAndSet無(wú)法保證處理操作目標(biāo)的volatile變量外的其他變量的執(zhí)行順序( 編譯器和處理器為了優(yōu)化程序性能而對(duì)指令序列進(jìn)行重新排序 ),同時(shí)也無(wú)法保證這些變量的可見(jiàn)性疙筹。
         */
        public final boolean weakCompareAndSet(V expect, V update) {
            return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
        }
    
        /**
         * 原子性的設(shè)置值并返回舊值
         */
        @SuppressWarnings("unchecked")
        public final V getAndSet(V newValue) {
            return (V)unsafe.getAndSetObject(this, valueOffset, newValue);
        }
    
        /**
         * 原子性地用給定函數(shù)的結(jié)果更新當(dāng)前值富俄,并返回舊值。
         */
        public final V getAndUpdate(UnaryOperator<V> updateFunction) {
            V prev, next;
            do {
                prev = get();
                next = updateFunction.apply(prev);
            } while (!compareAndSet(prev, next));
            return prev;
        }
    
        /**
         * 原子性地用給定函數(shù)的結(jié)果更新當(dāng)前值而咆,并返回新值霍比。
         */
        public final V updateAndGet(UnaryOperator<V> updateFunction) {
            V prev, next;
            do {
                prev = get();
                next = updateFunction.apply(prev);
            } while (!compareAndSet(prev, next));
            return next;
        }
    
        /**
         * 原子性地用給定函數(shù)的結(jié)果更新當(dāng)前值,并返回舊值暴备。
         *
         * BinaryOperator函數(shù)式接口:
         *
         * atomicReference.getAndAccumulate(2, (i, j) -> {
         *     log.info("i:" + i);
         *     log.info("j:" + j);
         *     return i + j;
         * });
         * i: value
         * j: 2
         */
        public final V getAndAccumulate(V x, BinaryOperator<V> accumulatorFunction) {
            V prev, next;
            do {
                prev = get();
                next = accumulatorFunction.apply(prev, x);
            } while (!compareAndSet(prev, next));
            return prev;
        }
    
        /**
         * 原子性地用給定函數(shù)的結(jié)果更新當(dāng)前值悠瞬,并返回新值。
         *
         * BinaryOperator函數(shù)式接口:
         * atomicReference.getAndAccumulate(2, (i, j) -> {
         *     log.info("i:" + i);
         *     log.info("j:" + j);
         *     return i + j;
         * });
         * i: value
         * j: 2
         */
        public final V accumulateAndGet(V x, BinaryOperator<V> accumulatorFunction) {
            V prev, next;
            do {
                prev = get();
                next = accumulatorFunction.apply(prev, x);
            } while (!compareAndSet(prev, next));
            return next;
        }
    
        /**
         * Returns the String representation of the current value.
         * @return the String representation of the current value
         */
        public String toString() {
            return String.valueOf(get());
        }
    
    }

2.4 AtomicIntegerFieldUpdater

AtomicIntegerArray要想原子地更新字段類需要如下過(guò)程

  • 因?yàn)樵痈伦侄晤惗际浅橄箢愨裳保看问褂玫臅r(shí)候必須使用靜態(tài)方法 newUpdater() 創(chuàng)建一個(gè)更新器阁危,并且需要設(shè)置想要更新的類和屬性。
  • 更新類的字段(屬性)必須使用 public汰瘫、volatile 修飾符狂打,且變量類型只能用int,不能使用Integer混弥。

AtomicIntegerArray就不貼源碼了趴乡,有點(diǎn)多,但是源碼不難蝗拿,看一看即可晾捏。貼一個(gè)使用的例子吧

    @Slf4j
    public class JunitTest {
    
        @Setter
        @Getter
        @AllArgsConstructor
        public class OrderTest {
            public volatile int age;
        }
    
        @Test
        public void test0() {
            OrderTest orderTest = new OrderTest(18);
    
            AtomicIntegerFieldUpdater orderTestUpdater = AtomicIntegerFieldUpdater.newUpdater(OrderTest.class, "age");
    
            orderTestUpdater.incrementAndGet(orderTest);
    
            orderTestUpdater.get(orderTest);
    
            log.info("age: "+ orderTest.age);
    
        }
    }

輸出結(jié)果為:

    age: 19
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市哀托,隨后出現(xiàn)的幾起案子惦辛,更是在濱河造成了極大的恐慌,老刑警劉巖仓手,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胖齐,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡嗽冒,警方通過(guò)查閱死者的電腦和手機(jī)呀伙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)添坊,“玉大人剿另,你說(shuō)我怎么就攤上這事。” “怎么了雨女?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵谚攒,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我戚篙,道長(zhǎng)五鲫,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任岔擂,我火速辦了婚禮位喂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘乱灵。我一直安慰自己塑崖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布痛倚。 她就那樣靜靜地躺著规婆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蝉稳。 梳的紋絲不亂的頭發(fā)上抒蚜,一...
    開(kāi)封第一講書(shū)人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音耘戚,去河邊找鬼嗡髓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛收津,可吹牛的內(nèi)容都是我干的饿这。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼撞秋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼长捧!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起吻贿,我...
    開(kāi)封第一講書(shū)人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤串结,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后舅列,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體奉芦,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年剧蹂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烦却。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宠叼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情冒冬,我是刑警寧澤伸蚯,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站简烤,受9級(jí)特大地震影響剂邮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜横侦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一挥萌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枉侧,春花似錦引瀑、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至翼虫,卻和暖如春屑柔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背珍剑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工掸宛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人次慢。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓旁涤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親迫像。 傳聞我的和親對(duì)象是個(gè)殘疾皇子劈愚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353