1、线程同步概述

线程之间有可能共享一些资源,比如内存、文件、数据库等。多个线程同时读写同一份共享资源时,就可能引起冲突,所以引入了线程的“同步”机制。

所谓同步,就是说线程要有先来后到,排队执行操作,而不是同时进行操作。目的就是为了防止多个线程在访问相同数据对象时,对数据造成污染和破坏。

为了实现同步,Java中提供了“锁”的机制,可以给共享资源加上一把锁,这把锁只有一把钥匙,哪个线程获取了这把钥匙,才有权利去访问该共享资源。而实现“锁”机制的关键字,就是 synchronized

2、synchronized

synchronized 的使用很简单
  • 同步方法:   访问权限修饰符  synchronized 数据返回类型 方法名() { ... }
  • 同步语句块:synchronized (共享对象名) { ... }
  • 不能修饰构造函数、抽象方法、成员变量

下面我们来看个简单的demo:
//Data 共享数据
public class Data { private static int count = 0; public static int getCount() {
return count;
} public static void add() {
count++;
} } //Counter 操作共享数据
public class Counter { public synchronized void count() {
Data.add();
System.out.println("current count = " + Data.getCount());
} } //MyThread
public class MyThread extends Thread { private Counter counter; public MyThread(Counter counter) {
this.counter = counter;
} @Override
public void run() {
for(int i = 0; i < 50; i++) {
counter.count();
}
} } //Test
public class Test {
public static void main(String[] args) {
Counter counter1 = new Counter();
Counter counter2 = new Counter(); Thread t1 = new MyThread(counter1);
Thread t2 = new MyThread(counter2);
t1.start();
t2.start();
}
} //输出结果示例
...
current count = 2
current count = 2
current count = 3
current count = 4
current count = 5
current count = 6
current count = 7
...
x
 
1
//Data 共享数据
2
public class Data {
3

4
    private static int count = 0;
5

6
    public static int getCount() {
7
        return count;
8
    }
9

10
    public static void add() {
11
        count++;
12
    }
13

14
}
15

16
//Counter 操作共享数据
17
public class Counter {
18

19
    public synchronized void count() {
20
        Data.add();
21
        System.out.println("current count = " + Data.getCount());
22
    }
23

24
}
25

26
//MyThread
27
public class MyThread extends Thread {
28

29
    private Counter counter;
30

31
    public MyThread(Counter counter) {
32
        this.counter = counter;
33
    }
34

35
    @Override
36
    public void run() {
37
        for(int i = 0; i < 50; i++) {
38
            counter.count();
39
        }
40
    }
41

42
}
43

44

45
//Test
46
public class Test {
47
    public static void main(String[] args) {
48
        Counter counter1 = new Counter();
49
        Counter counter2 = new Counter();
50

51
        Thread t1 = new MyThread(counter1);
52
        Thread t2 = new MyThread(counter2);
53
        t1.start();
54
        t2.start();
55
    }
56
}
57

58
//输出结果示例
59
...
60
current count = 2
61
current count = 2
62
current count = 3
63
current count = 4
64
current count = 5
65
current count = 6
66
current count = 7
67
...

如上例中,可以看到在 Counter 类的 count() 方法我们已经加上了 synchronized 关键字,该方法会将共享数据 Data.count 自增,然后进行打印输出。但是,我们发现输出的结果显示,count 竟然有重复,这意味着数据出现了脏读,我们在打印前,有其他线程对共享数据再次进行了修改!锁机制无效,为什么?

因为 synchronized 取得的锁是对象锁,而不是把一段代码或方法当成锁。这意味着,要实现同步,即某线程执行,其他线程等待,前提是多个线程访问的是同一个对象。而上例中,显然 counter1 和 counter2 是两个对象,我们的锁也就没有效果。

我们试着把两个线程的 Counter 类统一下,锁机制就如我们所愿了:
//Test
public class Test {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new MyThread(counter);
Thread t2 = new MyThread(counter);
t1.start();
t2.start();
}
} //输出结果示例
current count = 1
current count = 2
current count = 3
current count = 4
current count = 5
current count = 6
current count = 7
current count = 8
...
1
10
 
1
//Test
2
public class Test {
3
    public static void main(String[] args) {
4
        Counter counter = new Counter();
5
        Thread t1 = new MyThread(counter);
6
        Thread t2 = new MyThread(counter);
7
        t1.start();
8
        t2.start();
9
    }
10
}
11

12
//输出结果示例
13
current count = 1
14
current count = 2
15
current count = 3
16
current count = 4
17
current count = 5
18
current count = 6
19
current count = 7
20
current count = 8
21
...

最后,简单总结:
  • 只对改变共享资源的地方进行同步,而不是所有方法。同步块越大,多线程的效率也越低
  • synchronized 关键字可以修饰方法和代码块,但是不能修饰构造函数、抽象方法、成员变量
  • synchronized 关键字无法继承
  • synchronized 不论在方法还是对象上,取得的锁都是对象,注意搞清楚锁定的是哪个对象


[03] 线程同步 synchronized的更多相关文章

  1. Java线程(二):线程同步synchronized和volatile

    上篇通过一个简单的例子说明了线程安全与不安全,在例子中不安全的情况下输出的结果恰好是逐个递增的(其实是巧合,多运行几次,会产生不同的输出结果),为什么会产生这样的结果呢,因为建立的Count对象是线程 ...

  2. 线程同步 synchronized 同步代码块 同步方法 同步锁

    一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...

  3. 线程同步synchronized,wait,notifyAll 测试示例

    https://www.cnblogs.com/LipeiNet/p/6475851.html 一  synchronized synchronized中文解释是同步,那么什么是同步呢,解释就是程序中 ...

  4. 线程同步synchronized和ReentrantLock

    一.线程同步问题的产生及解决方案 问题的产生: Java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确,相互之间产生冲突. 如下例:假设有一个卖票 ...

  5. 多线程学习-基础( 九)线程同步Synchronized关键字

    一.线程同步1.synchronized关键字的作用域有二种:(1)某个对象实例内:synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果 ...

  6. Java线程同步synchronized的理解

    JVM中(留神:马上讲到的这两个存储区只在JVM内部与物理存储区无关)存在一个主内存(Main Memory),Java中所有的变量存储在主内存中,所有实例和实例的字段都在此区域,对于所有的线程是共享 ...

  7. java多线程:线程同步synchronized(不同步的问题、队列与锁),死锁的产生和解决

    0.不同步的问题 并发的线程不安全问题: 多个线程同时操作同一个对象,如果控制不好,就会产生问题,叫做线程不安全. 我们来看三个比较经典的案例来说明线程不安全的问题. 0.1 订票问题 例如前面说过的 ...

  8. Day13_71_线程同步(synchronized)

    线程同步 * 异步编程模型和同步编程模拟的区别? - 有T1和T2 两个线程 > 异步编程模型:T1线程执行T1的,T2线程执行T2的,谁也不等谁 > 同步编程模型:T1和T2 线程执行, ...

  9. C++并发编成 03 线程同步

    这一节主要讲讲线程同步的方式,C++ 11中提供了丰富的线程同步元语,如condition_variable,futrue,std::packaged_task<>,std::promis ...

随机推荐

  1. Python入门基础之条件判断、循环、dict和set

    Python之if语句 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,可以用if语句实现: age = 20 if age >= 18: print 'your age is ...

  2. loadrunner 脚本优化-检查点设置

    脚本优化-检查点设置 by:授客 QQ:1033553122 VuGen判断脚本是否执行成功是根据服务器返回的状态来确定的,如果服务器返回的是HTTP状态为200 OK,那么VuGen就认为脚本正确地 ...

  3. Windows上通过bat调用jmx进行循环运行

    1.jmx测试脚本中有两个线程组: 1)第一个线程组:模拟60台客户机并发像服务器发送上报请求,需要调用线程组的循环运行 2)第二个线程组:60台客户机上线后,模拟管理平台对客户机进行基础操作,如:创 ...

  4. mysql之数据备份与恢复

    本文内容: 复制文件法 利用mysqldump 利用select into outfile 其它(列举但不介绍) 首发日期:2018-04-19 有些时候,在备份之前要先做flush tables , ...

  5. java笔记----面试题总结(一)【转】

    1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: - 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪些属性和行为,并不关注 ...

  6. [20180914]oracle 12c 表 full_hash_value如何计算.txt

    [20180914]oracle 12c 表 full_hash_value如何计算.txt --//昨天在12c下看表full_hash_value与11g的full_hash_value不同,不过 ...

  7. Spring扫面路径配置不全导致异常 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): 的原因

    运行Junit测试类 package cn.bgodata.x.zero.service; import org.junit.Test; import org.junit.runner.RunWith ...

  8. SQL SERVER 查询表字段中是否有汉字

    SELECT * FROM TB WHERE COL LIKE N'%[吖-咗]%'

  9. python第一百一十七天-----ModelForm组件

    Model + Form => 验证 + 数据库操作 - class LoginModelForm(xxxxx): 利用model.A中的字段 1. 生成HTML标签:class Meta: . ...

  10. Mysql的NULL和Empty String

    本文基于Mysql5.7版本的参考资料: https://dev.mysql.com/doc/refman/5.7/en/working-with-null.html https://dev.mysq ...