同步代码块

基本语句

synchronized (任意对象) {

操作共享代码

}

代码示例


public class SellTicket implements Runnable {
private int tickets = 100;
private Object object = new Object(); @Override
public void run() {
while (true) {
synchronized (object) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
} public static void main(String[] args) { SellTicket sellTicket = new SellTicket(); Thread thread1 = new Thread(sellTicket, "窗口1");
Thread thread2 = new Thread(sellTicket, "窗口2");
Thread thread3 = new Thread(sellTicket, "窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}

优缺点:

  • 解决了多线程的数据安全问题
  • 多线程时,每个线程都会判断同步上的锁,耗费资源,降低了程序的运行效率

同步方法

同步方法:将synchronized关键字加到方法上

  • 格式: 修饰符 synchronized 返回值类型 方法名(){ }
  • 同步方法的锁对象是this

同步静态方法,就是把synchronized关键字加到静态方法上

  • 格式: 修饰符 static synchronized 返回值类型 方法名(){ }
  • 同步静态方法的锁对象是 类名.class

代码示例

public class SellTicket implements Runnable {
// private int tickets = 100;
private static int tickets = 100;
private Object object = new Object();
private int x = 0; @Override
public void run() {
while (true) {
if (x % 2 == 0) {
// synchronized (object) {
// synchronized (this) {
synchronized (SellTicket.class) {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
} else {
// synchronized (object) {
// if (tickets > 0) {
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
// tickets--;
// }
// }
sellTicket();
}
x++;
}
} // private void sellTicket(){
// synchronized (object) {
// if (tickets > 0) {
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
// tickets--;
// }
// }
// } // private synchronized void sellTicket(){
// if (tickets > 0) {
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
// tickets--;
// }
private static synchronized void sellTicket(){
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
} } public static void main(String[] args) { SellTicket sellTicket = new SellTicket(); Thread thread1 = new Thread(sellTicket, "窗口1");
Thread thread2 = new Thread(sellTicket, "窗口2");
Thread thread3 = new Thread(sellTicket, "窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}

lock锁

lock实现提供比使用synchronized方法和语句可获得更广泛的操作

  • void lock()获得锁
  • void unlock()释放

lock是接口不能直接实例化,采用实现类实例化ReentrantLock

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class SellTicket implements Runnable {
private int tickets = 100;
private Object object = new Object();
private Lock lock = new ReentrantLock(); @Override
public void run() {
while (true) {
try {
lock.lock();
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
} finally {
lock.unlock(); }
} } public static void main(String[] args) { SellTicket sellTicket = new SellTicket(); Thread thread1 = new Thread(sellTicket, "窗口1");
Thread thread2 = new Thread(sellTicket, "窗口2");
Thread thread3 = new Thread(sellTicket, "窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}

Java中解决多线程数据安全问题的更多相关文章

  1. java中的多线程 // 基础

    java 中的多线程 简介 进程 : 指正在运行的程序,并具有一定的独立能力,即 当硬盘中的程序进入到内存中运行时,就变成了一个进程 线程 : 是进程中的一个执行单元,负责当前程序的执行.线程就是CP ...

  2. Java中的多线程=你只要看这一篇就够了

    如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其 ...

  3. Java中的多线程技术全面详解

    本文主要从整体上介绍Java中的多线程技术,对于一些重要的基础概念会进行相对详细的介绍,若有叙述不清晰或是不正确的地方,希望大家指出,谢谢大家:) 为什么使用多线程 并发与并行 我们知道,在单核机器上 ...

  4. Java 中传统多线程

    目录 Java 中传统多线程 线程初识 线程的概念 实现线程 线程的生命周期 常用API 线程同步 多线程共享数据的问题 线程同步及实现机制 线程间通讯 线程间通讯模型 线程中通讯的实现 @(目录) ...

  5. Java中使用多线程、curl及代理IP模拟post提交和get访问

    Java中使用多线程.curl及代理IP模拟post提交和get访问 菜鸟,多线程好玩就写着玩,大神可以路过指教,小弟在这受教,谢谢! 更多分享请关注微信公众号:lvxing1788 ~~~~~~ 分 ...

  6. Java中的 多线程编程

    Java 中的多线程编程 一.多线程的优缺点 多线程的优点: 1)资源利用率更好2)程序设计在某些情况下更简单3)程序响应更快 多线程的代价: 1)设计更复杂虽然有一些多线程应用程序比单线程的应用程序 ...

  7. Android学习记录(5)—在java中学习多线程下载之断点续传②

    在上一节中我们学习了在java中学习多线程下载的基本原理和基本用法,我们并没有讲多线程的断点续传,那么这一节我们就接着上一节来讲断点续传,断点续传的重要性不言而喻,可以不用重复下载,也可以节省时间,实 ...

  8. Java中使用多线程、curl及代理IP模拟post提交和get訪问

    Java中使用多线程.curl及代理IP模拟post提交和get訪问 菜鸟,多线程好玩就写着玩.大神能够路过不吝赐教.小弟在这受教.谢谢! 很多其它分享请关注微信公众号:lvxing1788 ~~~~ ...

  9. java中解决组件重叠的问题(例如鼠标移动组件时)

    java中解决组件覆盖的问题!     有时候在移动组件的时候会出现两个组件覆盖的情况,但是你想让被覆盖的组件显示出来或者不被覆盖! 在设计GUI时已经可以定义组件的叠放次序了(按摆放组件的先后顺序) ...

随机推荐

  1. Redis主从,集群部署及迁移

    工作中有时会遇到需要把原Redis集群下线,迁移到另一个新的Redis集群的需求(如机房迁移,Redis上云等原因).此时原Redis中的数据需要如何操作才可顺利迁移到一个新的Redis集群呢? 本节 ...

  2. HTML骨架解析

    在VSCode中按下"!"感叹号便可得到如下的html骨架,没有这些骨架浏览器便不能正常渲染,但是这些骨架分别代表什么含义呢?不急,我们一行一行的看. 1 <!DOCTYPE ...

  3. 暑假自学java第一天

    今天通过网上的学习资料安装了Java的环境和java的程序开发工具包(JDK) 还安装了eclipse ,英语不太好,所以不太会用这个软件,网上搜了教程,还是出现了问题:unnamed package ...

  4. 资源:Postgresql数据库下载路径

    postgresql下载路径: https://www.enterprisedb.com/downloads/postgres-postgresql-downloads

  5. 我通过调试ConcurrentLinkedQueue发现一个IDEA的小虫子(bug), vscode复现, eclipse毫无问题

    前言: 本渣渣想分析分析Doug Lea大佬对高并发代码编写思路, 于是找到了我们今天的小主角ConcurrentLinkedQueue进行鞭打, 说实话草稿我都打好了, 就差临门一脚, 给踢折了 直 ...

  6. C语言:延时1秒

    使用sleep()函数将程序阻塞,头文件在windows系统和linux系统下是不一样的windowsSleep()//第一个字母大写#include <windows.h>函数原型voi ...

  7. 关于torch.nn.LSTM()的输入和输出

    主角torch.nn.LSTM() 初始化时要传入的参数 | Args: | input_size: The number of expected features in the input `x` ...

  8. Kubernetes部署-RKE自动化部署

    一.简介 RKE:Rancher Kubernetes Engine 一个极其简单,闪电般快速的Kubernetes安装程序,可在任何地方使用. 二.准备工作 I.配置系统 系统:CentOS 7 / ...

  9. MySQL中的redo log和undo log

    MySQL中的redo log和undo log MySQL日志系统中最重要的日志为重做日志redo log和归档日志bin log,后者为MySQL Server层的日志,前者为InnoDB存储引擎 ...

  10. 使用ThinkPHP5.0.12连接Mongo数据库的经验

    本地开发环境xamppv3.2.2,ThinkPHP5.0.12版本. 由于之前开发项目时使用的是TP3.2.3+mongo数据库,也是在本地进行的,所以也进行过mongo数据库驱动的配置.详细方法可 ...