Java线程同步操作
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线程同步操作的更多相关文章
- Java线程的概念
1. 计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...
- 第23章 java线程通信——生产者/消费者模型案例
第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...
- 第22章 java线程(2)-线程同步
java线程(2)-线程同步 本节主要是在前面吃苹果的基础上发现问题,然后提出三种解决方式 1.线程不安全问题 什么叫线程不安全呢 即当多线程并发访问同一个资源对象的时候,可能出现不安全的问题 对于前 ...
- Java线程并发中常见的锁
随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...
- Java线程并发中常见的锁--自旋锁 偏向锁
随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想 ...
- 浅谈Java线程安全
浅谈Java线程安全 - - 2019-04-25 17:37:28 线程安全 Java中的线程安全 按照线程安全的安全程序由强至弱来排序,我们可以将Java语言中各种操作共享的数据分为以下五类 ...
- java 线程的几种状态(转载)
java thread的运行周期中, 有几种状态, 在 java.lang.Thread.State 中有详细定义和说明: NEW 状态是指线程刚创建, 尚未启动 RUNNABLE 状态是线程正在 ...
- Java线程安全与多线程开发
互联网上充斥着对Java多线程编程的介绍,每篇文章都从不同的角度介绍并总结了该领域的内容.但大部分文章都没有说明多线程的实现本质,没能让开发者真正“过瘾”. 从Java的线程安全鼻祖内置锁介绍开始,让 ...
- 工作常用4种Java线程锁的特点,性能比较、使用场景
多线程的缘由 在出现了进程之后,操作系统的性能得到了大大的提升.虽然进程的出现解决了操作系统的并发问题,但是人们仍然不满足,人们逐渐对实时性有了要求. 使用多线程的理由之一是和进程相比,它是一种非常花 ...
随机推荐
- GoLang数组切片
1. 数组1.1 如何定义数组同java数组一样,数组是一组内存连续且类型相同的数据组成 //不初始化初始值默认为0 var arr1 = [5]int{} var arr2 = [5]int{1,2 ...
- CSS 面试题总结
CSS 中类 (classes) 和 ID 的区别. 书写上的差别:class名用"."号开头来定义,id名用"#"号开头来定义: 优先级不同(权重不同) 调用 ...
- 有关表单autocomplete = "off" 失效问题解决方案
一.autocomplete介绍 autocomplete是Html5中的新属性.该属性规定输入字段是否应该启用自动完成功能.自动完成允许浏览器预测对字段的输入.当用户在字段开始键入的时候,浏览器基于 ...
- 活字格发布新版本,插件公开,引领Web开发新潮流
日前,活字格Web 应用生成平台发布V4.0版本,首次公开插件机制,强大的扩展性和系统集成能力,引起业内瞩目. 活字格是由西安葡萄城自主研发的 Web 应用生成平台,提供易用的类Excel可视化设计器 ...
- Java-GUI编程之事件处理
事件处理 前面介绍了如何放置各种组件,从而得到了丰富多彩的图形界面,但这些界面还不能响应用户的任何操作.比如单击前面所有窗口右上角的"X"按钮,但窗口依然不会关闭.因为在 AWT ...
- 论文解读(GRCCA)《 Graph Representation Learning via Contrasting Cluster Assignments》
论文信息 论文标题:Graph Representation Learning via Contrasting Cluster Assignments论文作者:Chun-Yang Zhang, Hon ...
- Java学习——数组的基础知识
数组的特点.分类:一维.二维数组的使用:数组的声明和初始化.调用数组的指定位置的元素.获取数组的长度.遍历数组.数组元素的默认初始化值
- For-Each循环(增强型For循环)
public class Demo077 { public static void main(String[] args) { int[] array ={11,2}; System.out.prin ...
- python3-认识内置对象,运算符,表达式
1 . 认识内置对象 在python中一切皆对象, 整数,实数,复数,字符串,列表,元组,字典,集合,zip, map, enumerate, filter , 函数 ,类 , 分类:内置对象,标准 ...
- VMware虚拟机无法安装Win11解决方法 (暂时全网最全方案)
目录 1.现象 1.蓝屏重启 2.如下图示,无法启动 2.解决方案 2.1 Hyper-V方案 2.2 禁用 Device Guard(系统:win11) 2.3 升级虚拟机VMware pro的版本 ...