多线程(四)ThreadLocal与Synchonized的比较

源码解析访问:https://blog.csdn.net/qq_31129841/article/details/105551924(多线程:线程之间的共享和协作(二))

ThreadLocal和synchronized都用于解决多线程并发访问。

ThreadLocal与Synchronized本质区别:

①ThreadLocal为每个线程都提供了变量的副本,使得每个线程在某一时间访问到的并非同一个对象,这样就隔离了多个线程对数据的共享。

②synchronized是利用锁的机制,使变量或代码块在某一时刻仅仅能被一个线程访问。

例:

Spring的事务就借助了ThreadLocal类。 Spring会从数据库连接池中获得一个connection,然后会把connection放进ThreadLocal中,也就和线程绑定了,事务需要提交或者回滚,只要从ThreadLocal中拿到connection进行操作。

为何Spring的事务要借助ThreadLocal类?

以JDBC为例,正常的事务代码如下:

dbc=newDataBaseConnection();//第 1 行 
Connectioncon=dbc.getConnection();//第 2 行 
con.setAutoCommit(false);//第 3 行 
con.executeUpdate(...);//第 4 行 
con.executeUpdate(...);//第 5 行 
con.executeUpdate(...);//第 6 行 
con.commit();//第 7 行

大致划分为三部分:

        ①事务准备阶段:1~3行;

        ②业务处理阶段:4~6行;

        ③事务提交阶段:第7行。

       不管开启事务还是执行具体的SQL都需要一个具体的数据库连接。

       我们开发商业项目一般采用三层结构,如果控制事务的代码都放在DAO(DataAccessObject)对象中,在DAO对象的每个方法当中去打开事务关闭事务,当Service对象在调用DAO时,如果只调用一个DAO,我们这样实现则效果不错,但往往我们的Service会调用一系列的DAO对数据库进行多次操作,这个时候我们就无法控制事务的边界了,因为实际应用当中,Service调用的DAO的个数是不确定的,可根据需求而变化,而且还可能出现Service调用Service的情况。

       如果不使用ThreadLocal,代码大概就是这个样子:

public void serviceOrder() {
		Connection conn = null;
		try {
			conn = getConnection();
			conn.setAutoCommit(false);
			Dao1 dao1 = new Dao1(conn);
			dao1.doSomething();
			Dao2 dao2 = new Dao2(conn);
			dao2.doSomething();
			Dao3 dao3 = new Dao3(conn);
			dao3.doSomething();
			conn.commit();
		} catch (Exception e) {
			throw e;
		}
	}
private Connection conn = null;
	public Dao1(Connection conn) {
		this.conn = conn;
	}
	public void doSomething() {
		PreparedStatement pstmt = null;
		try {
			pstmt = conn.prepareStatement(sql);
			pstmt.execute();
		} catch (Exception e) {
			throw e;
		}
	}

       需要注意的是:如果让三个DAO使用同一个数据源连接呢? 就必须为每个DAO传递同一个数据库连接,要么就是在DAO实例化的时候作为构造方法的参数传递,要么在每个DAO的实例方法中作为方法的参数传递。这两种方式对Spring框架或者码农来说都不合适。为了让这个数据库连接可以跨阶段传递,又不显示的进行参数传递,就必须使用别的方式方法。

       Web容器中,每个完整的请求周期会由一个线程来处理,因此,如果能将一些参数绑定到线程的话,就可以实现在软件架构中跨层次的参数共享(是隐式共享)。而Java中恰好提供了绑定的方法——》使用ThreadLocal

       只要将一个数据库连接放入ThreadLocal中,当前线程执行时只要有使用数据库连接的地方,就从ThreadLocal获取。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值