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. DevEco Device Tool 3.0 Release 新版本发布,支持多人共享开发

    DevEco Device Tool 是面向智能设备开发者提供的一站式集成开发环境,支持 HarmonyOS Connect 的组件按需定制,支持代码编辑.编译.烧录和调试.性能监测等功能,支持 C/ ...

  2. c源文件中为什么要包含自己对应的头文件

    另一篇:.c文件和.h文件的关系 引言: 我们经常在c工程中发现,源文件中要包含自己的头文件.一直以来,都不知道为什么这样做.现在,我知道了. 以前的认知: 我认为,.c文件没有必要包含自己的.h文件 ...

  3. 学习HTML5 history API

    html5 在 history 对象上添加几个新的方法.事件.属性,用以增强开发者对于浏览器历史记录的控制.大体上说,新的API可以帮助我们在无刷新的情况下改变浏览器的url,新增或者替换之前的历史记 ...

  4. transformjs 污染了 DOM?是你不了解它的强大

    原文链接:https://github.com/AlloyTeam/AlloyTouch/wiki/Powerful-transformjs 写在前面 上星期在React微信群里,有小伙伴觉得tran ...

  5. ES6-11学习笔记--类与继承

    ES5 中的类与继承: 类的定义: function People(name, age) { // this指向当前实例化对象 console.log(this); // 实例属性 this.name ...

  6. Android Studio安装问题

    安装问题可以参考:https://blog.csdn.net/y74364/article/details/96121530 但是gradle安装缓慢,需要FQ.有加速器FQ的可以开加速器安装,没有的 ...

  7. CSS简单样式练习(七)

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

  8. 这道javascript 面试题 你必须会

    实现一个函数,运算结果可以满足如下预期结果: add(1)(2) // 3 add(1, 2, 3)(10) // 16 add(1)(2)(3)(4)(5) // 15 话不多说,实现如下: fun ...

  9. Spring Security 一键接入验证码登录和小程序登录

    最近实现了一个多端登录的Spring Security组件,用起来非常丝滑,开箱即用,可插拔,而且灵活性非常强.我觉得能满足大部分场景的需要.目前完成了手机号验证码和微信小程序两种自定义登录,加上默认 ...

  10. 变量 数据类型 条件if语句

    python是解释型  弱类型编程语言;  "优雅", "明确", "简单";  开发效率非常高;  可移植性;  可扩展性; 可嵌入型. ...