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. c语言代码规范

    什么叫规范?在C语言中不遵守编译器的规定,编译器在编译时就会报错,这个规定叫作规则.但是有一种规定,它是一种人为的.约定成俗的,即使不按照那种规定也不会出错,这种规定就叫作规范.虽然我们不按照规范也不 ...

  2. [C/C++基础知识] main函数的参数argc和argv

    该篇文章主要是关于C++\C语言最基础的main函数的参数知识,是学习C++或C语言都必备的知识点.不知道你是否知道该知识?希望对大家有所帮助.一.main()函数参数通常我们在写主函数时都是void ...

  3. 用纯CSS美化radio和checkbox

    Radio和checkbox需要美化吗?答案是必须的,因为设计风格一直都会变化,原生的样式百年不变肯定满足不了需求. 先看看纯CSS美化过后的radio和checkbox效果:查看. 项目地址:mag ...

  4. win10 Celery异步任务报错: Task handler raised error: ValueError('not enough values to unpack (expected 3, got 0)

    示例代码如下: from celery import Celery app = Celery('tasks', backend='redis://×××:6379/1', broker='redis: ...

  5. CentOS 7.9 网络配置

    vi /etc/sysconfig/network-scripts/ifcfg-ens33 (45条消息) CentOS 7.9 网络配置_$青的博客-CSDN博客_centos7.9网卡配置

  6. java中字符串池,String池,共享池到底是怎么回事?

    栈中有共享池的概念,比 如下面例子中,sz="hello";在栈中创建一个String对象引用变量sz,然后看看栈中有没有"hello",如果没有,则将&quo ...

  7. SpringMVC 配置和请求方式

    SpringMVC 总结内容 一.什么是 Spring MVC ? Spring MVC 是 Spring 对 MVC 思想的实现(三层架构) 优点: 二.前端控制器 Spring MVC 中的前端控 ...

  8. vConsole移动端调试利器

    图示: ,  简单的几步操作: 1. 引入cdn     可以从https://www.bootcdn.cn/vConsole/下载,也可以下载保存在本地,直接引用 <!DOCTYPE html ...

  9. 防止自己的页面不被其他网站的页面的iframe引用

    方法用二: 一.设置http请求头的X-Frame-Options: X-Frame-Options可以设置三个值 1.DENY  代表页面不会能被嵌入到iframe或者frame里 2.SAMEOR ...

  10. 修复tunl0-二进制安装calico

    这篇博文很重要,出现这个问题导致pod之间无法通讯,pod无法连接外网. 出现的问题是二进制方式安装了节点之后, tunl0没有显示,通过ifconfig tunl0 up 启动tunl0 没有意义, ...