关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象。本文探讨synchronized关键字。

synchronized关键字可以修饰方法,可以修饰代码块,但不能修饰构造器、属性等。

对synchronized(this)的一些理解

  1. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
  2. 当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
  3. 然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的除synchronized(this)同步代码块以外的部分。
  4. 第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
  5. 以上规则对其它对象锁同样适用。

一:synchronized同步代码块

public class SyncThread1 implements Runnable {
private Integer key = 0; @Override
public void run() {
// key是Integer对象(注意不是int,因为int不是对象)
// 线程进入下面同步代码之前,需要先获取key的锁。
// 需要结果是key实现自增长,如果没有同步块,则可能会出现重复key值的现象
synchronized (key) {
key++; System.out.println(Thread.currentThread().getName() + ":" + key);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
} public static void main(String[] args) {
SyncThread1 st = new SyncThread1(); for(int i=0; i<10; i++) {
new Thread(st, "Thread" + i).start();
}
}
}

输出:

Thread1:2
Thread3:3
Thread5:4
Thread7:5
Thread0:2
Thread2:7
Thread9:6
Thread4:8
Thread6:9
Thread8:10

二:synchronized同步方法

同步方法分静态和非静态两种。静态方法则一定会同步,非静态方法需在单例模式才生效,推荐用静态方法(不用担心是否单例)。

2.1 非静态方法同步示范

// 如果是同步方法,则分静态和非静态两种。
// 静态方法则一定会同步,非静态方法需在单例模式才生效,推荐用静态方法(不用担心是否单例)。
public class SyncThread2 implements Runnable {
private Integer key = 0; // 此示范为非静态方法同步
public synchronized Integer getKey() {
key++; return key;
} @Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":" + getKey());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
} public static void main(String[] args) {
// 非静态方法同步,需要启动单例模式
SyncThread2 st = new SyncThread2();
for (int i = 0; i < 10; i++) {
new Thread(st, "Thread" + i).start();
}
}
}

输出:

Thread0:1
Thread1:3
Thread2:2
Thread3:5
Thread5:6
Thread7:7
Thread9:8
Thread6:9
Thread8:10
Thread4:4

2.2 静态方法同步示范

// 如果是同步方法,则分静态和非静态两种。
// 静态方法则一定会同步,非静态方法需在单例模式才生效,推荐用静态方法(不用担心是否单例)。
public class SyncThread3 implements Runnable {
private static Integer key = 0; // 此示范为静态方法同步
public synchronized static Integer getKey() {
key++; return key;
} @Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":" + getKey());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
} public static void main(String[] args) { // 如果用静态方法实现同步,则可以生成对象的多个实例
for (int i = 0; i < 10; i++) {
SyncThread3 st = new SyncThread3();
new Thread(st, "Thread" + i).start();
}
}
}

输出:

Thread3:3
Thread1:1
Thread0:2
Thread5:4
Thread7:5
Thread9:6
Thread2:7
Thread8:10
Thread6:9
Thread4:8

总结

1、无论是同步代码块还是同步方法,必须获得对象锁才能够进入同步代码块或者同步方法进行操作。

2、如果采用方法级别的同步,对象锁为方法所在的对象;如果是静态同步方法,对象锁为方法所在的类(唯一)。

3、对于代码块,对象锁即指synchronized(object)中的object。

转自:https://www.cnblogs.com/nayitian/p/3258536.html

云时代架构阅读笔记七——Java多线程中如何使用synchronized关键字的更多相关文章

  1. 云时代架构阅读笔记六——Java内存模型详解(二)

    承接上文:云时代架构阅读笔记五——Java内存模型详解(一) 原子性.可见性.有序性 Java内存模型围绕着并发过程中如何处理原子性.可见性和有序性这三个特征来建立的,来逐个看一下: 1.原子性(At ...

  2. 云时代架构阅读笔记一——Java性能优化(一)

    Java语言学习了这么长时间之后,自己对于Java编程的一些细节还是稍微有点总结,正好根据云时代架构中<Java高级开发必会的50个性能优化的细节(珍藏版)>来叙述一些我和里面的点比较相符 ...

  3. 云时代架构阅读笔记二——Java性能优化(二)

    承接上文Java性能优化(一)https://www.cnblogs.com/guo-xu/p/11019267.html 4)尽量确定StringBuffer的容量 在说和这个标题相关之前,先说一下 ...

  4. 云时代架构阅读笔记五——Java内存模型详解(一)

    什么是Java内存模型 Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽掉各种硬件和操作系统的访问差异,以实现让Java程序在各种平台下都能达到一致 ...

  5. 云时代架构阅读笔记十五——之前碰到的Java面试题

    1.一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致. 2.Java有 ...

  6. 云时代架构阅读笔记十六——Hystrix理解

    背景 分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务.如下图,对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能导致整个商品服 ...

  7. 云时代架构阅读笔记十四——我对Hash算法的理解

    Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是 ...

  8. 云时代架构阅读笔记十一——数据库SQL优化

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 ...

  9. 云时代架构阅读笔记九——web应用存在的问题及解决办法

    web应用通常存在的10大安全问题 1.SQL注入 拼接的SQL字符串改变了设计者原来的意图,执行了如泄露.改变数据等操作,甚至控制数据库服务器, SQL Injection与Command Inje ...

随机推荐

  1. virtual column make sqlserver using function index

    In sqlserver, it is impossible that if we want to create an function index. Doesn`t means we can not ...

  2. 多用类型常量,少用#define预处理指令

    摒弃: #define ANIMATION_DURATION 0.3   #define ERROR_MESSAGE @“ErrorMessage” 1)没有常量的类型信息 2)假设此指令声明在某个头 ...

  3. 排序--选择排序Selection Sort Java实现

    基本原理 选择排序的简单原理:选择排序算法通过从未排序部分重复查找最小元素(考虑升序)并将其放在开头来对数组进行排序. 将数组两个子数组: 已排序子数组 未排序子数组 选择排序中每次循环都会从未排序子 ...

  4. C 语言入门第五章--循环结构和选择结构

    C语言中有三大结构,分别是顺序结构.选择结构和循环结构: 逻辑运算: 与运算: && 或运算:|| 非运算:! ==== #include<stdio.h> int mai ...

  5. 记录要做的事情,把sql字符串替换写成工具网页。

    之前使用的是java的本地控制台进行sql占位符的替换. 现在我想换个方式,想到了两种. 第一种是使用java +jsp进行替换,前台输出. 第二种是把java代码改成js代码,反正也不用访问数据库. ...

  6. JS数据统计表 highcharts.js的运用

    参考地址 http://www.runoob.com/highcharts/highcharts-column-basic.html 1.下载JS文件引入,或者用CDN function getCou ...

  7. Maven:sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

    还是记录使用 maven 时遇到的问题. 一.maven报错 maven package 进行打包时出现了以下报错: Non-resolvable parent POM for com.wpbxin: ...

  8. 车林通购车之家--购车计算器模块js实现

    //jsq-nav.twig <ul class="switch-nav db-tags bgfff clearfix"> <li id="qk&quo ...

  9. @vue-cli的安装及vue项目创建

    1.安装 Node.js & Vue CLI @vue/cli3,是vue-进行搭建的脚手架项目,它本质上是一个全局安装的 npm 包,通过安装它,可以为终端提供 vue 命令,进行vue项目 ...

  10. express写的接口在疯狂刷新几十次后,服务器挂掉

    用到的命令行: show status like 'Threads%'; show variables like '%max_connections%'; show global status lik ...