1、数据库事务基础知识

    1)数据库事务有严格的定义,它必须同时满足4个特性:原子性(Atomic)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),简称ACID。
    2)数据并发的问题:脏读、不可重复读、幻想读、第一类丢失更新、第二类丢失更新。
    3)数据库锁机制:
        按锁定的对象的不同:一般可以分别表锁定和行锁定,前者对整个表进行锁定,而后者对表中特定行进行锁定。从并发事务锁定的关系上看,可以分为共享锁定和独占锁定。共享锁定会防止独占锁定,但允许其他的共享锁定。而独占锁定既防止其他的独占锁定,也防止其他的共享锁定。为了更改数据,数据库必须在进行更改的行上施加行独占锁定,INSERT、UPDATE、DELETE和SELECT FOR UPDATE语句都会隐式采用必要的行锁定。
    4)事务隔离级别:READ UNCOMMITED 、 READ COMMITTED、REPEATABLE READ、SERIALIZABLE。
    5)JDBC对事务支持
        用户可以通过Connection#getMetaData()方法获取DatabaseMetaData对象,并通过该对象的supportsTransactions()、supportsTransactionIsolationLevel(int level)方法查看底层数据库的事务支持情况。Connection默认情况下是自动提交的,也即每条执行的SQL都对应一个事务,为了能够将多条SQL当成一个事务执行,必须先通过Connection#setAutoCommit(false)阻止Connection自动提交,并可通过Connection#setTransactionIsolation()设置事务的隔离级别,Connection中定义了对应SQL92标准4个事务隔离级别的常量。通过Connection#commit()提交事务,通过Connection#rollback()回滚事务。
    典型的JDBC事务数据操作的代码:

Connection conn;
try{
conn = DriverManager.getConnection();
conn.setAutoCommit(false);
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
Statement stmt = conn.createStatement();
int rows = stmt.executeUpdate("INSERT INTO t_topic VALUES(1,'tom')");
rows = stmt.executeUpdate("UPDATE t_user set topic_nums = topic_nums + 1 WHERE user_id = 1"); conn.commit();
}catch(Exception e){
...
conn.rollback();
}finally(
...
)
2、ThreadLocal基础知识
    ThreadLocal,顾名思义,他不是一个线程,而是线程的一个本地化对象。当工作于多线程中的对象使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程分配一个独立的变量副本。所以每一个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。从线程的角度看,这个变量就像是线程的本地变量,这也是类名中“Local”所要表达的意思。
    ThreadLocal类接口很简单,只有4个方法:
    1)void set(Object value):设置当前线程的线程局部变量的值;
    2)public Object get():该方法返回当前线程所对应的线程局部变量;
    3)public void remove():将当前线程局部变量的值删除,目的是为了减少内存的利用。
    4)protected Object initialValue():返回该线程局部变量的初始值。
    ThreadLocal是如何做到为每一个线程维护一份独立的变量副本呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素键为线程对象,而值对应线程的变量副本。
简单的实现版本:

package com.yyq.transaction;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class SimpleThreadLocal {
private Map valueMap = Collections.synchronizedMap(new HashMap());
public void set(Object newValue){
valueMap.put(Thread.currentThread(),newValue);
} public Object get(){
Thread currentThread = Thread.currentThread();
Object o = valueMap.get(currentThread);
if (o == null && !valueMap.containsKey(currentThread)){
o = initialValue();
valueMap.put(currentThread,o);
}
return o;
} public void remove(){
valueMap.remove(Thread.currentThread());
} public Object initialValue(){
return null;
}
}

一个ThreadLocal实例:

package com.yyq.transaction;
public class SequenceNumber {
private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {
public Integer initialValue() {
return 0;
}
};
public int getNextNum() {
seqNum.set(seqNum.get() + 1);
return seqNum.get();
}
private static class TestClient extends Thread {
private SequenceNumber sn;
public TestClient(SequenceNumber sn) {
this.sn = sn;
}
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("thread[" + Thread.currentThread().getName() + "]sn[" + sn.getNextNum() + "]");
}
}
}
public static void main(String[] args) {
SequenceNumber sn = new SequenceNumber();
TestClient t1 = new TestClient(sn);
TestClient t2 = new TestClient(sn);
TestClient t3 = new TestClient(sn);
t1.start();
t2.start();
t3.start();
}
}
输出结果:
thread[Thread-1]sn[1]
thread[Thread-1]sn[2]
thread[Thread-1]sn[3]
thread[Thread-0]sn[1]
thread[Thread-0]sn[2]
thread[Thread-0]sn[3]
thread[Thread-2]sn[1]
thread[Thread-2]sn[2]
thread[Thread-2]sn[3]
 
    根据输出结果可以发现每个线程所产生的序号虽然都共享同一个SequenceNumber实例,但它们并没有发生相互干扰的情况,而是各自产生独立的序列号,这是因为我们通过ThreadLocal为每一个线程提供了单独的副本。
    在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序缜密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。
    而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal为每一个线程提供一个独立的变量副本,从而隔离了多个线程对访问数据的冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对变量进行同步了。ThreadLocal提供了线程安全的对象封装,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。
    概况起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式:访问串行化,对象共享化。而ThreadLocal采用了“以空间换时间”的方式:访问并行化,对象独享化。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。

Spring的事务管理基础知识的更多相关文章

  1. [Spring框架]Spring 事务管理基础入门总结.

    前言:在之前的博客中已经说过了数据库的事务, 不过那里面更多的是说明事务的一些锁机制, 今天来说一下Spring管理事务的一些基础知识. 之前的文章: [数据库事务与锁]详解一: 彻底理解数据库事务一 ...

  2. Spring事务管理——基础会用篇

    之前说到Spring的事务管理 一直很懵逼 ,只知道事务管理大概是干嘛的. 网上的博客都是用 银行转账来解释 事务管理,哈哈哈 那我也用这个吧,这个例子的确是最好的. 说是两个人相互转账,A转500块 ...

  3. 【Spring】Spring的事务管理 - 1、Spring事务管理概述(数据库事务、Spring事务管理的核心接口)

    Spring事务管理概述 文章目录 Spring事务管理概述 数据库事务 什么是Spring的事务管理? Spring对事务管理的支持 Spring事务管理的核心接口 Platform Transac ...

  4. Spring应用——事务管理

    事务基础:请参看:http://www.cnblogs.com/solverpeng/p/5720306.html 一.Spring 事务管理 1.前提:事务管理器 在使用 Spring 声明式事务管 ...

  5. spring+mybatis事务管理

    spring+mybatis事务管理 最近在和朋友做一个项目,考虑用springmvc+mybatis来做,之前在公司工作吧,对于数据库这块的配置也有人再弄,最近因为这个项目,我就上网学习了一些关于数 ...

  6. Spring之事务管理

        事务管理对于企业应用至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.     就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到 ...

  7. Hibernate与Spring的事务管理

    什么是事务 这个问题比较大,按照我的理解就是,一个事务内的n个操作,要么全部完成,一旦有一个操作有问题,那么所有的操作都全部回滚. Jdbc的事务 首先,大家已经知道了,事务说白了就是一个词----统 ...

  8. Spring Boot事务管理(中)

    在上一篇 Spring Boot事务管理(上)的基础上介绍Spring Boot事务属性和事务回滚规则 . 4 Spring Boot事务属性 什么是事务属性呢?事务属性可以理解成事务的一些基本配置, ...

  9. Spring Boot事务管理(下)

    在上两篇 Spring Boot事务管理(上)和Spring Boot事务管理(中)的基础上介绍注解@Transactional. 5 @Transactional属性 属性 类型 描述 value ...

随机推荐

  1. 微信小程序中的单位

    vw:viewpoint width,视窗宽度,1vw等于视窗宽度的1%. vh:viewpoint height,视窗高度,1vh等于视窗高度的1%. rpx:rpx单位是微信小程序中css的尺寸单 ...

  2. 实验楼-Git实战教程

    实验1-git介绍 1.版本控制系统: 1)集中式版本控制系统:版本库是集中存放在中央服务器的,工作时需要先从中央服务器取得最新的版本,然后工作完成后把自己的修订推送给中央服务器.这类系统都有一个单一 ...

  3. new Random().Next(1, 100); 多线程同时执行结果很高概率相同,

    /// <summary> /// new Random().Next(1, 100); 多线程同时执行结果很高概率相同, /// 是用的当前时间为seed,时间相同结果相同 /// // ...

  4. 枚举进行位运算 枚举组合z

    枚举进行位运算--枚举组合 public enum MyEnum { MyEnum1 = , //0x1 MyEnum2 = << , //0x2 MyEnum3 = << , ...

  5. Spark2.3(四十三):Spark Broadcast总结

    为什么要使用广播(broadcast)变量? Spark中因为算子中的真正逻辑是发送到Executor中去运行的,所以当Executor中需要引用外部变量时,需要使用广播变量.进一步解释: 如果exe ...

  6. HashMap代码解析

    hashmap (jdk 1.7)使用 “数组-链表” 方式进行存储,图形化表示如下: 即,前面是一个数组,后面跟一个链表,那么数据结构这个对应到HashMap的代码里面是什么样子的呢? 在HashM ...

  7. 读吴恩达算-EM算法笔记

    最近感觉对EM算法有一点遗忘,在表述的时候,还是有一点说不清,于是重新去看了这篇<CS229 Lecture notes>笔记. 于是有了这篇小札. 关于Jensen's inequali ...

  8. CentOS 7.4安装nodejs & nginx & pm2

    一.安装nodejs1.查看操作系统信息 uname -a cat /etc/centos-release 2.安装wget yum install wget -y3.安装nodejs 1.下载 wg ...

  9. SNF软件开发机器人-子系统-功能-数据录入方式

    数据录入方式 数据录入方式是指新增数据时是直接在列表上添加或者弹出表单增加数据. 1.效果展示: (1)列表 (2)表单弹出 2.使用说明: 打开显示页面,点击开发者选项的简单配置按钮.在功能表信息中 ...

  10. 性能测试相关(TPS/RT/PV等)(转)

    对于我们开发来说,我们日常最熟悉的工作就是把客户的需求实现并交付.但是,事情并不是往往就这样结束了,我们还需要后续对上线的系统进行跟踪调查,查看系统的运行情况.为什么呢?一方面,我们需要关注系统在运行 ...