synchronized

作用于对象实例:对给定对象加锁,进入同步代码前要获得给定对象的锁。

作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。

作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。

使用

给实例对象加锁

public class AccountingSync implements Runnable {
static AccountingSync instance = new AccountingSync();
static int i = 0; @Override
public void run() {
for (int k = 0; k < 10000; k++) {
synchronized (instance) {
i++;
}
}
} @Test
public void testInteger() throws InterruptedException {
int count = 10;
Thread[] ts = new Thread[count]; for (int k = 0; k < count; k++) {
ts[k] = new Thread(instance);
} // start
for (int k = 0; k < count; k++) {
ts[k].start();
} // join
for (int k = 0; k < count; k++) {
ts[k].join();
} System.out.println(i);
}
}

给类方法加锁

public class AccountingSync2 implements Runnable {
static AccountingSync2 instance = new AccountingSync2();
static int i = 0; public synchronized void increase() {
i++;
} @Override
public void run() {
for (int k = 0; k < 10000; k++) {
increase();
}
} @Test
public void testInteger() throws InterruptedException {
int count = 10;
Thread[] ts = new Thread[count]; for (int k = 0; k < count; k++) {
ts[k] = new Thread(instance);
} // start
for (int k = 0; k < count; k++) {
ts[k].start();
} // join
for (int k = 0; k < count; k++) {
ts[k].join();
} System.out.println(i);
}
}

给类方法加锁的错误演示

public class AccountingSyncBad implements Runnable {
static int i = 0; public synchronized void increase() {
i++;
} @Override
public void run() {
for (int k = 0; k < 10000; k++) {
increase();
}
} @Test
public void testInteger() throws InterruptedException {
int count = 10;
Thread[] ts = new Thread[count]; for (int k = 0; k < count; k++) {
ts[k] = new Thread(new AccountingSyncBad());
} // start
for (int k = 0; k < count; k++) {
ts[k].start();
} // join
for (int k = 0; k < count; k++) {
ts[k].join();
} System.out.println(i);
}
}

假设把给类实例加锁中的每个实例比作一个门,上面的测试方法中每个门都有锁但是10个门10把锁,每个线程进一个门。还是不能保证临界区资源i同时只一个线程访问

fix

@Test
public void testIntegerFix() throws InterruptedException {
int count = 10;
AccountingSyncBad instance = new AccountingSyncBad();
Thread[] ts = new Thread[count]; for (int k = 0; k < count; k++) {
ts[k] = new Thread(instance);
} // start
for (int k = 0; k < count; k++) {
ts[k].start();
} // join
for (int k = 0; k < count; k++) {
ts[k].join();
} System.out.println(i);
}

给静态类方法加锁

public class AccountingSyncClass implements Runnable {
static int i = 0; public static synchronized void increase() {
i++;
} @Override
public void run() {
for (int k = 0; k < 10000; k++) {
increase();
}
} @Test
public void testInteger() throws InterruptedException {
int count = 10;
Thread[] ts = new Thread[count]; for (int k = 0; k < count; k++) {
ts[k] = new Thread(new AccountingSyncClass());
} // start
for (int k = 0; k < count; k++) {
ts[k].start();
} // join
for (int k = 0; k < count; k++) {
ts[k].join();
} System.out.println(i);
} @Test
public void testIntegerFix() throws InterruptedException {
int count = 10;
AccountingSyncClass instance = new AccountingSyncClass();
Thread[] ts = new Thread[count]; for (int k = 0; k < count; k++) {
ts[k] = new Thread(instance);
} // start
for (int k = 0; k < count; k++) {
ts[k].start();
} // join
for (int k = 0; k < count; k++) {
ts[k].join();
} System.out.println(i);
}
}

上面测试的testInteger方法和testIntegerFix方法都能得到正确的结果,原因是给静态类方法加锁相当于10个门用的同一把锁,保证了同一时间只有一个线程能访问临界区资源i。

Java线程同步操作的更多相关文章

  1. Java线程的概念

    1.      计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...

  2. 第23章 java线程通信——生产者/消费者模型案例

    第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...

  3. 第22章 java线程(2)-线程同步

    java线程(2)-线程同步 本节主要是在前面吃苹果的基础上发现问题,然后提出三种解决方式 1.线程不安全问题 什么叫线程不安全呢 即当多线程并发访问同一个资源对象的时候,可能出现不安全的问题 对于前 ...

  4. Java线程并发中常见的锁

    随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...

  5. Java线程并发中常见的锁--自旋锁 偏向锁

    随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...

  6. 浅谈Java线程安全

    浅谈Java线程安全 - - 2019-04-25    17:37:28 线程安全 Java中的线程安全 按照线程安全的安全程序由强至弱来排序,我们可以将Java语言中各种操作共享的数据分为以下五类 ...

  7. java 线程的几种状态(转载)

      java thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明: NEW 状态是指线程刚创建, 尚未启动 RUNNABLE 状态是线程正在 ...

  8. Java线程安全与多线程开发

    互联网上充斥着对Java多线程编程的介绍,每篇文章都从不同的角度介绍并总结了该领域的内容.但大部分文章都没有说明多线程的实现本质,没能让开发者真正“过瘾”. 从Java的线程安全鼻祖内置锁介绍开始,让 ...

  9. 工作常用4种Java线程锁的特点,性能比较、使用场景

    多线程的缘由 在出现了进程之后,操作系统的性能得到了大大的提升.虽然进程的出现解决了操作系统的并发问题,但是人们仍然不满足,人们逐渐对实时性有了要求. 使用多线程的理由之一是和进程相比,它是一种非常花 ...

随机推荐

  1. 在网页中预览excel表格文件

    项目需求在前端页面中实现预览excel表格的功能,上网了解之后大致总结为一下几种方法. 1.office文档转换为pdf,再转swf,然后通过网页加载flash进行预览 2.通过 xlsx.js,js ...

  2. PAT B1086 就不告诉你

    题目描述: 做作业的时候,邻座的小盆友问你:"五乘以七等于多少?"你应该不失礼貌地围笑着告诉他:"五十三."本题就要求你,对任何一对给定的正整数,倒着输出它们的 ...

  3. java基础-多线程线程池

    线程池 * 程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互.而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池.线程池里的每一个线程代 ...

  4. 微信小程序时间戳转为日期格式

    通常后台传递过来的都是时间戳,但是前台展示不能展示时间戳.就需要转化了. 功能说明: 微信小程序里,时间戳转化为日期格式,支持自定义. 拷贝至项目utils/utils.js中,并注意在js中声明下: ...

  5. JavaScript实现带正则表达式的表单校验(校验成功后跳转)

    运行结果: 源代码: 1 <!DOCTYPE html> 2 <html lang="zh"> 3 <head> 4 <meta char ...

  6. 多条命令同时执行的包concurrently

    npm i concurrently use "script":{ "client:build": "webpack --config build/w ...

  7. intel 82599网卡(ixgbe系列)术语表

    Intel® 82599 10 GbE Controller Datasheet 15.0 Glossary and Acronyms 术语表 缩写 英文解释 中文解释 1 KB A value of ...

  8. 『忘了再学』Shell基础 — 8、管道符介绍

    我们之前已经有文章说过管道符了,今天这里再简单总结一下用法. 1.行提取命令grep grep命令的作用,是在指定的文件中,搜索符合条件的字符串. 命令格式: [root@localhost ~ ] ...

  9. String类 的基本用法

    1.String 对象的创建 String对象的创建有两种方式. 第1 种方式就是我们最常见的创建字符串的方式: String str1 = "Hello, 慕课网"; 第 2 种 ...

  10. 虚拟机安装linux

    https://blog.csdn.net/wujiele/article/details/92803655https://www.cnblogs.com/yunwangjun-python-520/ ...