好记性不如烂笔头76-多线程-通过synchronized实现资源同步

来源:互联网 发布:php __isset 在哪用 编辑:程序博客网 时间:2024/05/29 17:55

每个对象都有一个标志锁。当对象的一个线程访问了对象的某个synchronized数据(包括函数)时,这个对象就将被“上锁”,被声明为synchronized的数据(包括函数)都不能被调用(因为当前线程取走了对象的“锁标志”)。
只有当前线程访问完它要访问的synchronized数据,释放“锁标志”后,同一个对象的其它线程才能访问synchronized数据。
注意:每个class也有一个“锁标志”。对于synchronized static数据(包括函数)可以在整个class下进行锁定,避免static数据的同时访问。

  • 样例的场景

我们的业务需要获取一个序列号。下面是一个取得序列号的单例模式的例子,利用 synchronized 对get()函数进行约束,避免产生两个相同的序列号。

  • 利用synchronized实现资源同步的java源代码
package com.thread;/** * 利用synchronized 避免多线程获取重复序列号 * @author 范芳铭 */public class EasySynchronizedGetSeq extends Thread {    private static int number = 0;    private static EasySynchronizedGetSeq seq = new EasySynchronizedGetSeq();    public EasySynchronizedGetSeq(String name){        super(name);    }    private EasySynchronizedGetSeq() {    }    public   EasySynchronizedGetSeq getInstance() {        return seq;    }    public synchronized   int get() {        number++; // (a)        return number;// (b)    }    public void run(){        for (int i = 0 ; i < 10; i ++){            int a = getInstance().get();// (1)            System.out.println(Thread.currentThread().getName() + ":" + a);            //模拟访问停顿            try {                Thread.sleep(10);            } catch (Exception e) {                e.printStackTrace();            }        }       }    public static void main(String[] args) {        //简单模拟多线程调用        EasySynchronizedGetSeq sepA = new EasySynchronizedGetSeq("A");        sepA.start();        EasySynchronizedGetSeq sepB = new EasySynchronizedGetSeq("---B");        sepB.start();        EasySynchronizedGetSeq sepC = new EasySynchronizedGetSeq("======C");        sepC.start();    }}

运行结果
A:1
—B:2
======C:3
A:4
—B:6
======C:5
—B:7
A:8
======C:9
A:11
======C:12
—B:10
======C:13
—B:15
A:14
—B:16
A:18
======C:17
A:20
—B:21
======C:19
—B:23
A:24
======C:22
—B:25
A:27
======C:26
A:29
—B:30
======C:28

要证明错误很容易,只要有一个反例;但是要证明对很不容易,这个需要一整套的逻辑和支撑。
因此,这个结论,只是一个大概的结论。

0 0
原创粉丝点击