手机版
你好,游客 登录 注册 搜索
背景:
阅读新闻

Java锁机制 synchronized 详解

[日期:2018-01-26] 来源:Linux社区  作者:QG-whz [字体: ]

进行多线程编程的时候,需要考虑的是线程间的同步问题。对于共享的资源,需要进行互斥的访问。在Java中可以使用一些手段来达到线程同步的目的:

1. synchronized

2. ThreadLocal,线程本地变量

3. Java.util.concurrent.Lock

Java中,线程会共享堆上的实例变量以及方法区的类变量,而栈上的数据是私有的,不必进行保护。synchronized方法或synchronized块将标记一块监视区域,线程在进入该区域时,需要获得对象锁或类锁,JVM将自动上锁。在这里,我们将探讨synchronized使用时的三种情况:

1. 在对象上使用synchronized

2. 在普通成员方法上使用synchronized

3. 在静态成员方法上使用synchronized

这三种线程同步的表现有何不同?

下面通过三段示例代码来演示这三种情况。这里模拟线程报数的场景。

情况一:在普通成员函数上使用synchronized

public class MyThread extends Thread {

    public static void main(String[] args) throws Exception {
        for (int i = 1; i < 100; i++) {
            MyThread t  = new MyThread();
            t.setName("Thread="+i);
            t.start();
            Thread.sleep(100);
        }
    }

    @Override
    public synchronized void run() {
        for (int i = 1; i < 10000; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}

对一个成员函数使用synchronized进行加锁,所获取的锁,是方法所在对象本身的对象锁。在这里,每个线程都以自身的对象作为对象锁,要对线程进行同步,要求锁对象必须唯一,所以这里多个线程间同步失败。

情况二:在对象上使用synchronized

这里在类中增加一个成员变量lock,在该变量上使用synchronized:

public class MyThread1 extends Thread {

    private String lock;

    public MyThread1(String lock) {
        this.lock = lock;
    }

    public static void main(String[] args) throws Exception {
        String lock = new String("lock");
        for (int i = 1; i < 100; i++) {
            Thread t = new MyThread1(lock);
            t.setName("Thread=" + i);
            t.start();
            Thread.sleep(100);
        }
    }

    @Override
    public void run() {
        synchronized (lock) {
            for (int i = 1; i < 10000; i++) {
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

100个线程在创建的时候,都传递了同一个lock对象(在main中创建的)去初始化线程类成员lock,因此,这100个线程都在同一个lock对象上进行synchronized同步。因此线程同步成功。

情况三:在静态成员函数上使用synchronized

public class MyThread2 extends Thread {


    public static void main(String[] args) throws Exception {

        for (int i = 1; i < 10; i++) {
            Thread t = new MyThread2();
            t.setName("Thread=" + i);
            t.start();
            Thread.sleep(10);
        }
    }

    public static synchronized void func() {
        for (int i = 1; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }

    @Override
    public void run() {
        func();
    }
}

这种情况下,线程获得的锁是对象锁,而对象锁是唯一的,因此多个进程间也能同步成功。

本文永久更新链接地址http://www.linuxidc.com/Linux/2018-01/150575.htm

linux
相关资讯       Java synchronized  Java锁机制 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款