1 . 多个线程访问多个对象JVM会创建多个锁。
2 . 静态方法是以类为单位进行同步的——对于同一个类中的所有静态方法,在同一时间内,只允许有一个线程执行其中的一个静态方法,其余想要进入这些方法的线程都必须挂起等待。非静态方法是以对象为单位进行同步的。
3 .假设现有两个线程A和B,一个object对象,当线程A调用object对象的一个同步方法M1时,线程A就获得了M1方法所在对象的锁,所以其他线程必须等待线程A执行完毕之后才能调用方法M1,如果线程B调用object的同步方法M2,必须等待线程A将M1方法执行完 ,也就是释放对象锁后才可以调用 ;但是线程B可以随意调用其他其他的非同步方法。
4 .synchronized具有锁重入(自己可以再次获取自己的内部锁)的功能:当一个线程得到一个对象锁后再次请求此对象锁时可以再次得到该对象的锁。即在一个同步方法/块内部调用本类的其他同步方法/块是永远可以得到锁的。可重入锁也支持在父子类继承的关系中即子类可以通过可重入锁调用父类的同步方法。

/*** 此类用于演示锁重入的概念* * 可重入锁:自己可以再次获取自己的内部锁。例如一个线程获得了某个对象的锁,此时这个对象还没有释放,当其再次想要获取这个对象的锁的时候还是可以获得,* 如果不可锁重入的话,则会造成死锁,并且当存在父子集成关系时,子类完全可以通过"可重入锁"调用父类的同步方法* * @Description* @author niepei* @date 2017年4月25日 下午3:52:41* @version V1.3.1*/
public class LockReentry {public synchronized void service1() {System.out.println("service1");this.service2();}public synchronized void service2() {System.out.println("service2");this.service3();}public synchronized void service3() {System.out.println("service3");}public static void main(String[] args) {Thread thread = new Thread() {@Overridepublic void run() {LockReentry service = new LockReentry();service.service1();}};thread.start();}
}

5 . 当一个线程执行的代码出现异常,其持有的锁会自动释放
6 .同步不能被继承,比如父类的service()方法是同步的,子类继承了父类,子类中的service()方法需要声明为synchronized。
7 . 当使用synchronized代码块时需要注意,如果一个线程访问object的一个同步代码块,其他线程对同一个object的所有其他的同步代码块的的访问将被阻塞
8 . 多线程的死锁:当双方互相持有对方的锁的时候就会出现死锁,即只要互相等待对方释放锁就有可能出现死锁。下面这段代码为线程死锁示例:

public class DeadThread implements Runnable {private String username;private Object lock1 = new Object();private Object lock2 = new Object();public void setFlag(String username) {this.username = username;}@Overridepublic void run() {if (username.equals("a")) {synchronized (lock1) {System.out.println("username = " + username);try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}synchronized (lock2) {System.out.println("按 lock1 -> lock2 代码顺序执行了");}}}if (username.equals("b")) {synchronized (lock2) {System.out.println("username = " + username);try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}synchronized (lock1) {System.out.println("按 lock2 -> lock1 代码顺序执行了");}}}}public static void main(String[] args) throws InterruptedException {DeadThread dt = new DeadThread();dt.setFlag("a");Thread a = new Thread(dt);a.setName("A");a.start();Thread.sleep(1000);dt.setFlag("b");Thread b = new Thread(dt);b.setName("B");b.start();}}运行结果为:
username = a
username = b

9 . volatile关键字的作用是使实例变量在多个线程间可见,可以强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值。

  • volatile 是线程同步的轻量级实现,所以性能肯定比synchronized好,并且volatile只能用于修饰变量,而synchronized可以修饰方法,代码块
  • 多线程访问volatile不会发生阻塞,而synchronized会出现阻塞
  • volatile能保证数据的可见性,但是不能保证原子性,而synchronized既能保证原子性也能间接保证可见性(通过将私有内存和公共内存的数据做同步实现)
  • volatile解决的是变量在多个线程之间的可见性,而synchronized解决的是多个线程之间访问资源的同步性
  • 线程安全包括原子性和同步性,java的同步机制都是围绕这两个方面来确保线程安全的

10 .synchronized关键字可以保证在同一时刻只有一个线程可以执行某个方法或者或者某段代码块,他包含两个特征:互斥性和可见性。synchronized不仅可以解决一个线程看到对象处于不一致的状态,还可以保证进入同步方法或者同步代码块的每个线程,都看到由同一个锁保护之前所有的修改结果

11.类ReentrantLock具有完全互斥排他的效果,即同一时间只有一个线程可以执行lock后面的代码,这样虽然保证了实例变量的安全性但是效率比较低,未解决这个问题可以使用ReentrantReadWriteLock类,在某些不需要使用实例变量的方法中可以使用ReentrantReadWriteLock来提高下效率.读写锁也有两个锁,一个读锁(共享锁)一个写锁(互斥锁)。读读共享,读写互斥,写写互斥。即多个Thread可以同时进行读操作,但同一时刻只有一个线程可以进行写操作。

package cn.com.thread;import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLock {private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();public void read() {try {lock.readLock().lock();System.out.println(Thread.currentThread().getName() + "在" + System.currentTimeMillis() / 1000 + "时刻获得了读锁");Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();} finally {lock.readLock().unlock();}}public void write() {try {lock.writeLock().lock();System.out.println(Thread.currentThread().getName() + "在" + System.currentTimeMillis() / 1000 + "时刻获得了写锁");Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();} finally {lock.writeLock().unlock();}}public static void main(String[] args) {//读读共享
        testReadReadLock();/*** 打印结果如下:* R1在1493257634时刻获得了读锁* R2在1493257634时刻获得了读锁*///读写互斥
        testReadWriteLock();/*** 打印结果如下: * R在1493258342时刻获得了读锁 * W在1493258343时刻获得了写锁*///写写互斥
        testWriteWriteLock();/*** 打印结果如下: * W1在1493259822时刻获得了写锁* W2在1493259823时刻获得了写锁*/}public static void testReadReadLock() {ReadWriteLock lock = new ReadWriteLock();new ReadThread("R1",lock).start();new ReadThread("R2",lock).start();}public static void testReadWriteLock() {ReadWriteLock lock = new ReadWriteLock();new ReadThread("R",lock).start();new WriteThread("W",lock).start();}public static void testWriteWriteLock() {ReadWriteLock lock = new ReadWriteLock();new WriteThread("W1",lock).start();new WriteThread("W2",lock).start();}}
/*** 读线程* @Description * @author niepei* @date 2017年4月27日 上午10:05:57 * @version V1.3.1*/
class ReadThread extends Thread {private ReadWriteLock lock;public ReadThread(String name, ReadWriteLock lock) {super(name);this.lock = lock;}@Overridepublic void run() {lock.read();}
}
/*** 写线程* @Description * @author niepei* @date 2017年4月27日 上午10:05:46 * @version V1.3.1*/
class WriteThread extends Thread {private ReadWriteLock lock;public WriteThread(String name, ReadWriteLock lock) {super(name);this.lock = lock;}@Overridepublic void run() {lock.write();}
}

转载于:https://www.cnblogs.com/pepper7/p/7196894.html

多线程--对象及变量的并发访问相关推荐

  1. 两个线程同时访问一个变量_百战程序员:Java多线程对象及变量的并发访问

    在开发多线程程序时,如果每个多线程处理的事情都不一样,每个线程都互不相关,这样开发的过程就非常轻松.但是很多时候,多线程程序是需要同时访问同一个对象,或者变量的.这样,一个对象同时被多个线程访问,会出 ...

  2. java 并发变量_二、Java多线程编程 (对象及变量的并发访问)

    非线程安全 多个线程对同一个对象中的实例变量进行并发操作时会出现值被更改.值不同步的情况,进而影响程序的执行流程. 线程安全 线程安全就是获得实例变量的值是经过同步处理的.不会出现被更改不同步的情况. ...

  3. 对象及变量的并发访问(案例加总结)--学习笔记

    文章目录 前言 一.synchronized的使用? 1.0.1 实际变量非线程安全及解决 1.0.2 当类中存在同步方法与非同步方法时(synchronized锁的是对象,而非方法) 1.0.3 s ...

  4. 对象及变量的并发访问一

    一.多个线程操作一个对象实例  当两个线程同时访问一个没有同步的方法,如果两个线程同时操作业务对象中的实例变量,则有可能会出现"非线程安全问题". 1 package concur ...

  5. Java-对象及变量的并发访问小结

    1)多线程环境下,方法内的变量是线程安全的 2)多个线程同时处理一个实例,这个实例内的变量是不安全的 3)不同线程中注入同一个类的不同实例,实例中的变量是安全的 4)Synchronized获取到的锁 ...

  6. 多线程中数据的并发访问与保护

    在多线程编程中,不可避免地要对一些共享的数据进行访问.由于线程之间对共享数据的访问是独立的,任何一个线程都可对共享数据进行访问和修改,且它们之间是异步并发进行的,特别是当需要对共享数据进行修改时,就会 ...

  7. Java并发编程(03):多线程并发访问,同步控制

    本文源码:GitHub·点这里 || GitEE·点这里 一.并发问题 多线程学习的时候,要面对的第一个复杂问题就是,并发模式下变量的访问,如果不理清楚内在流程和原因,经常会出现这样一个问题:线程处理 ...

  8. ios并发会造成什么问题_iOS Core data多线程并发访问的问题

    大家都知道Core data本身并不是一个并发安全的架构:不过针对多线程访问带来的问题,Apple给出了很多指导:同时很多第三方的开发者也贡献了很多解决方法.不过最近碰到的一个问题很奇怪,觉得有一定的 ...

  9. iOS使用多线程提高数据并发访问 之七

    活跃性 活跃性是指好的事情最终会发生.例如,如果你代码的目标是确保你能够持续从数组中push和pop对象,问题是这个过程是否能够永远工作.使用锁带来的问题是锁会引起系统中所有线程一直等待 -- 换句话 ...

  10. 【译文】 C#面向对象的基本概念 (Basic C# OOP Concept) 第一部分(类,对象,变量,方法,访问修饰符)...

    译文出处:http://www.codeproject.com/Articles/838365/Basic-Csharp-OOP-Concept 相关文档:http://files.cnblogs.c ...

最新文章

  1. 员工培训:如何制定以数据为依据的业务决策
  2. Wireshark非标准分析port无流量
  3. 新装的oracle缺少很多文件夹,丢失所有文件、拥有全备份,缺少后增加的文件
  4. 常见的网站服务器架构有哪些?
  5. mysql数据库安全审计_MySQL数据库安全日志审计工具
  6. 进程间基于共享存储区的通信_IPC(进程间通讯):inter process communication
  7. Python3生成脚本实现重置键盘键位
  8. MIUI V5正式发布 全部功能展示PPT回看
  9. sublime 关闭自动更新
  10. java中的容器问题
  11. PDF转换技巧之如何把文件转换为WPS?
  12. pfa100_什么是PFA?
  13. C语言程序设计(第三版)何钦铭著 习题2-1
  14. 成手指状态html,css手势状态定义属性cursor和自定义鼠标手势详解
  15. 如何给扑克洗牌才能更公平?
  16. Bus error的调试解决方法
  17. 2007版本中国网络新秀之七剑下天山
  18. 去掉最高分和最低分的平均分trimmean,计算频率最高的那个数即众数mode.sngl,判断数据是否重复
  19. MTK6735 android开发记录 编译配置(一)
  20. 1123_AURIX_TC275_DAP接口学习

热门文章

  1. 时间序列深度学习:状态 LSTM 模型预测太阳黑子(上)
  2. Centos7_系统初始优化配置
  3. Oracle如何实现利用实体化视图提高查询性能
  4. appium 原理解析(转载雷子老师博客)
  5. html css回顾总结
  6. Hadoop之倒排索引
  7. ADO.NET DataReader对象简介
  8. Py之pandas:dataframe学习【转载】
  9. oracle 之 cursor:创建存储过程批量执行DDL语句
  10. _DEVOBJ_EXTENSION结构体