精华内容
下载资源
问答
  • 【MySQL笔记】正确理解MySQL的MVCC及实现原理

    万次阅读 多人点赞 2019-07-05 15:43:06
    当前读 像 select lock in share mode (共享锁), select for update; update; insert; delete (排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能...

    MVCC多版本并发控制


    如果觉得对你有帮助,能否点个赞或关个注,以示鼓励笔者呢?!博客目录 | 先点这里

    !首先声明,MySQL 的测试环境是 5.7

    • 前提概要
      • 什么是 MVCC
      • 什么是当前读和快照读?
      • 当前读,快照读和 MVCC 的关系
    • MVCC 实现原理
      • 隐式字段
      • undo日志
      • Read View
      • 整体流程
    • MVCC 相关问题
      • RR 是如何在 RC 级的基础上解决不可重复读的?
      • RC, RR 级别下的 InnoDB 快照读有什么不同?

    前提概要


    什么是 MVCC ?

    MVCC
    MVCC,全称 Multi-Version Concurrency Control ,即多版本并发控制。MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。
    mvcc - @百度百科

    MVCCMySQL InnoDB 中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读


    什么是当前读和快照读?

    在学习 MVCC 多版本并发控制之前,我们必须先了解一下,什么是 MySQL InnoDB 下的当前读快照读?

    • 当前读
      像 select lock in share mode (共享锁), select for update; update; insert; delete (排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁

    • 快照读
      不加锁的 select 操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即 MVCC ,可以认为 MVCC 是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本

    说白了 MVCC 就是为了实现读-写冲突不加锁,而这个读指的就是快照读, 而非当前读,当前读实际上是一种加锁的操作,是悲观锁的实现


    当前读,快照读和MVCC的关系

    • MVCC 多版本并发控制是 「维持一个数据的多个版本,使得读写操作没有冲突」 的概念,只是一个抽象概念,并非实现
    • 因为 MVCC 只是一个抽象概念,要实现这么一个概念,MySQL 就需要提供具体的功能去实现它,「快照读就是 MySQL 实现 MVCC 理想模型的其中一个非阻塞读功能」。而相对而言,当前读就是悲观锁的具体功能实现
    • 要说的再细致一些,快照读本身也是一个抽象概念,再深入研究。MVCC 模型在 MySQL 中的具体实现则是由 3 个隐式字段undo 日志Read View 等去完成的,具体可以看下面的 MVCC 实现原理

    MVCC 能解决什么问题,好处是?

    数据库并发场景有三种,分别为:

    • 读-读:不存在任何问题,也不需要并发控制
    • 读-写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读
    • 写-写:有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失

    MVCC 带来的好处是?
    多版本并发控制(MVCC)是一种用来解决读-写冲突无锁并发控制,也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。 所以 MVCC 可以为数据库解决以下问题

    • 在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
    • 同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题

    小结一下咯
    简而言之,MVCC 就是因为大佬们,不满意只让数据库采用悲观锁这样性能不佳的形式去解决读-写冲突问题,而提出的解决方案,所以在数据库中,因为有了 MVCC,所以我们可以形成两个组合:

    • MVCC + 悲观锁
      MVCC解决读写冲突,悲观锁解决写写冲突
    • MVCC + 乐观锁
      MVCC 解决读写冲突,乐观锁解决写写冲突

    这种组合的方式就可以最大程度的提高数据库并发性能,并解决读写冲突,和写写冲突导致的问题


    MVCC 的实现原理


    MVCC 的目的就是多版本并发控制,在数据库中的实现,就是为了解决读写冲突,它的实现原理主要是依赖记录中的 3个隐式字段undo日志Read View 来实现的。所以我们先来看看这个三个 point 的概念

    隐式字段

    每行记录除了我们自定义的字段外,还有数据库隐式定义的 DB_TRX_ID, DB_ROLL_PTR, DB_ROW_ID 等字段

    • DB_TRX_ID
      6 byte,最近修改(修改/插入)事务 ID:记录创建这条记录/最后一次修改该记录的事务 ID
    • DB_ROLL_PTR
      7 byte,回滚指针,指向这条记录的上一个版本(存储于 rollback segment 里)
    • DB_ROW_ID
      6 byte,隐含的自增 ID(隐藏主键),如果数据表没有主键,InnoDB 会自动以DB_ROW_ID产生一个聚簇索引
    • 实际还有一个删除 flag 隐藏字段, 既记录被更新或删除并不代表真的删除,而是删除 flag 变了

    在这里插入图片描述
    如上图,DB_ROW_ID 是数据库默认为该行记录生成的唯一隐式主键,DB_TRX_ID 是当前操作该记录的事务 ID ,而 DB_ROLL_PTR 是一个回滚指针,用于配合 undo日志,指向上一个旧版本


    undo日志

    undo log 主要分为两种:

    • insert undo log
      代表事务在 insert 新记录时产生的 undo log, 只在事务回滚时需要,并且在事务提交后可以被立即丢弃
    • update undo log
      事务在进行 updatedelete 时产生的 undo log ; 不仅在事务回滚时需要,在快照读时也需要;所以不能随便删除,只有在快速读或事务回滚不涉及该日志时,对应的日志才会被 purge 线程统一清除

    purge

    • 从前面的分析可以看出,为了实现 InnoDB 的 MVCC 机制,更新或者删除操作都只是设置一下老记录的 deleted_bit ,并不真正将过时的记录删除。

    • 为了节省磁盘空间,InnoDB 有专门的 purge 线程来清理 deleted_bit 为 true 的记录。为了不影响 MVCC 的正常工作,purge 线程自己也维护了一个read view(这个 read view 相当于系统中最老活跃事务的 read view );如果某个记录的 deleted_bit 为 true ,并且 DB_TRX_ID 相对于 purge 线程的 read view 可见,那么这条记录一定是可以被安全清除的。

    对 MVCC 有帮助的实质是 update undo logundo log 实际上就是存在 rollback segment 中旧记录链,它的执行流程如下:

    一、 比如一个有个事务插入 persion 表插入了一条新记录,记录如下,name 为 Jerry , age 为 24 岁,隐式主键是 1,事务 ID回滚指针,我们假设为 NULL

    二、 现在来了一个事务 1对该记录的 name 做出了修改,改为 Tom

    • 事务 1修改该行(记录)数据时,数据库会先对该行加排他锁
    • 然后把该行数据拷贝到 undo log 中,作为旧记录,既在 undo log 中有当前行的拷贝副本
    • 拷贝完毕后,修改该行name为Tom,并且修改隐藏字段的事务 ID 为当前事务 1的 ID, 我们默认从 1 开始,之后递增,回滚指针指向拷贝到 undo log 的副本记录,既表示我的上一个版本就是它
    • 事务提交后,释放锁

    三、 又来了个事务 2修改person 表的同一个记录,将age修改为 30 岁

    • 事务2修改该行数据时,数据库也先为该行加锁
    • 然后把该行数据拷贝到 undo log 中,作为旧记录,发现该行记录已经有 undo log 了,那么最新的旧数据作为链表的表头,插在该行记录的 undo log 最前面
    • 修改该行 age 为 30 岁,并且修改隐藏字段的事务 ID 为当前事务 2的 ID, 那就是 2 ,回滚指针指向刚刚拷贝到 undo log 的副本记录
    • 事务提交,释放锁

    从上面,我们就可以看出,不同事务或者相同事务的对同一记录的修改,会导致该记录的undo log成为一条记录版本线性表,既链表,undo log 的链首就是最新的旧记录,链尾就是最早的旧记录(当然就像之前说的该 undo log 的节点可能是会 purge 线程清除掉,向图中的第一条 insert undo log,其实在事务提交之后可能就被删除丢失了,不过这里为了演示,所以还放在这里


    Read View 读视图

    什么是 Read View?

    什么是 Read View,说白了 Read View 就是事务进行快照读操作的时候生产的读视图 (Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的 ID (当每个事务开启时,都会被分配一个 ID , 这个 ID 是递增的,所以最新的事务,ID 值越大)

    所以我们知道 Read View 主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个 Read View 读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。

    Read View遵循一个可见性算法,主要是将要被修改的数据的最新记录中的 DB_TRX_ID(即当前事务 ID )取出来,与系统当前其他活跃事务的 ID 去对比(由 Read View 维护),如果 DB_TRX_ID 跟 Read View 的属性做了某些比较,不符合可见性,那就通过 DB_ROLL_PTR 回滚指针去取出 Undo Log 中的 DB_TRX_ID 再比较,即遍历链表的 DB_TRX_ID(从链首到链尾,即从最近的一次修改查起),直到找到满足特定条件的 DB_TRX_ID , 那么这个 DB_TRX_ID 所在的旧记录就是当前事务能看见的最新老版本

    那么这个判断条件是什么呢?
    在这里插入图片描述
    我们这里盗窃@呵呵一笑百媚生一张源码图,如上,它是一段 MySQL 判断可见性的一段源码,即 changes_visible 方法(不完全哈,但能看出大致逻辑),该方法展示了我们拿 DB_TRX_ID 去跟 Read View 某些属性进行怎么样的比较

    在展示之前,我先简化一下 Read View,我们可以把 Read View 简单的理解成有三个全局属性

    • trx_list(名称我随意取的)
      • 一个数值列表
      • 用于维护 Read View 生成时刻系统 正活跃的事务 ID 列表
    • up_limit_id
      • lower water remark
      • 是 trx_list 列表中事务 ID 最小的 ID
    • low_limit_id
      • hight water mark
      • ReadView 生成时刻系统尚未分配的下一个事务 ID ,也就是 目前已出现过的事务 ID 的最大值 + 1
      • 为什么是 low_limit ? 因为它也是系统此刻可分配的事务 ID 的最小值
    • 首先比较 DB_TRX_ID < up_limit_id , 如果小于,则当前事务能看到 DB_TRX_ID 所在的记录,如果大于等于进入下一个判断
    • 接下来判断 DB_TRX_ID >= low_limit_id , 如果大于等于则代表 DB_TRX_ID 所在的记录在 Read View 生成后才出现的,那对当前事务肯定不可见,如果小于则进入下一个判断
    • 判断 DB_TRX_ID 是否在活跃事务之中,trx_list.contains (DB_TRX_ID),如果在,则代表我 Read View 生成时刻,你这个事务还在活跃,还没有 Commit,你修改的数据,我当前事务也是看不见的;如果不在,则说明,你这个事务在 Read View 生成之前就已经 Commit 了,你修改的结果,我当前事务是能看见的

    整体流程

    我们在了解了 隐式字段undo log, 以及 Read View 的概念之后,就可以来看看 MVCC 实现的整体流程是怎么样了

    整体的流程是怎么样的呢?我们可以模拟一下

    • 事务 2对某行数据执行了快照读,数据库为该行数据生成一个Read View读视图,假设当前事务 ID 为 2,此时还有事务1事务3在活跃中,事务 4事务 2快照读前一刻提交更新了,所以 Read View 记录了系统当前活跃事务 1,3 的 ID,维护在一个列表上,假设我们称为trx_list
    事务 1事务 2事务 3事务 4
    事务开始事务开始事务开始事务开始
    修改且已提交
    进行中快照读进行中
    • Read View 不仅仅会通过一个列表 trx_list 来维护事务 2执行快照读那刻系统正活跃的事务 ID 列表,还会有两个属性 up_limit_idtrx_list 列表中事务 ID 最小的 ID ),low_limit_id ( 快照读时刻系统尚未分配的下一个事务 ID ,也就是目前已出现过的事务ID的最大值 + 1 资料传送门 | 呵呵一笑百媚生的回答 ) 。所以在这里例子中 up_limit_id 就是1,low_limit_id 就是 4 + 1 = 5,trx_list 集合的值是 1, 3,Read View 如下图
    • 我们的例子中,只有事务 4 修改过该行记录,并在事务 2 执行快照读前,就提交了事务,所以当前该行当前数据的 undo log 如下图所示;我们的事务 2 在快照读该行记录的时候,就会拿该行记录的 DB_TRX_ID 去跟 up_limit_id , low_limit_id活跃事务 ID 列表( trx_list )进行比较,判断当前事务 2能看到该记录的版本是哪个。
    • 所以先拿该记录 DB_TRX_ID 字段记录的事务 ID 4 去跟 Read Viewup_limit_id 比较,看 4 是否小于 up_limit_id( 1 ),所以不符合条件,继续判断 4 是否大于等于 low_limit_id( 5 ),也不符合条件,最后判断 4 是否处于 trx_list 中的活跃事务, 最后发现事务 ID 为 4 的事务不在当前活跃事务列表中, 符合可见性条件,所以事务 4修改后提交的最新结果对事务 2 快照读时是可见的,所以事务 2 能读到的最新数据记录是事务4所提交的版本,而事务4提交的版本也是全局角度上最新的版本

    在这里插入图片描述

    • 也正是 Read View 生成时机的不同,从而造成 RC , RR 级别下快照读的结果的不同

    MVCC 相关问题


    RR 是如何在 RC 级的基础上解决不可重复读的?

    当前读和快照读在 RR 级别下的区别:

    表1:

    事务A事务B
    开启事务开启事务
    快照读(无影响)查询金额为500快照读查询金额为500
    更新金额为400
    提交事务
    select 快照读金额为500
    select lock in share mode当前读金额为400

    在上表的顺序下,事务 B 的在事务 A 提交修改后的快照读是旧版本数据,而当前读是实时新数据 400

    表2:

    事务A事务B
    开启事务开启事务
    快照读(无影响)查询金额为500
    更新金额为400
    提交事务
    select 快照读金额为400
    select lock in share mode当前读金额为400

    而在表 2这里的顺序中,事务 B 在事务 A 提交后的快照读和当前读都是实时的新数据 400,这是为什么呢?

    • 这里与上表的唯一区别仅仅是表 1的事务 B 在事务 A 修改金额前快照读过一次金额数据,而表 2的事务B在事务A修改金额前没有进行过快照读。

    所以我们知道事务中快照读的结果是非常依赖该事务首次出现快照读的地方,即某个事务中首次出现快照读的地方非常关键,它有决定该事务后续快照读结果的能力

    我们这里测试的是更新,同时删除更新也是一样的,如果事务B的快照读是在事务A操作之后进行的,事务B的快照读也是能读取到最新的数据的


    RC , RR 级别下的 InnoDB 快照读有什么不同?

    正是 Read View 生成时机的不同,从而造成 RC , RR 级别下快照读的结果的不同

    • 在 RR 级别下的某个事务的对某条记录的第一次快照读会创建一个快照及 Read View, 将当前系统活跃的其他事务记录起来,此后在调用快照读的时候,还是使用的是同一个 Read View,所以只要当前事务在其他事务提交更新之前使用过快照读,那么之后的快照读使用的都是同一个 Read View,所以对之后的修改不可见;
    • 即 RR 级别下,快照读生成 Read View 时,Read View 会记录此时所有其他活动事务的快照,这些事务的修改对于当前事务都是不可见的。而早于Read View创建的事务所做的修改均是可见
    • 而在 RC 级别下的,事务中,每次快照读都会新生成一个快照和 Read View , 这就是我们在 RC 级别下的事务中可以看到别的事务提交的更新的原因

    总之在 RC 隔离级别下,是每个快照读都会生成并获取最新的 Read View;而在 RR 隔离级别下,则是同一个事务中的第一个快照读才会创建 Read View, 之后的快照读获取的都是同一个 Read View。


    MySQL系列


    参考资料


    展开全文
  • 正确理解ThreadLocal

    万次阅读 2007-07-28 11:24:00
    先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。另外...

    先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。

    另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行 ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为map的key来使用的。

    如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。

    下面来看一个hibernate中典型的ThreadLocal的应用:

    代码
    1. private static final ThreadLocal threadSession = new ThreadLocal();  
    2.   
    3. public static Session getSession() throws InfrastructureException {  
    4.     Session s = (Session) threadSession.get();  
    5.     try {  
    6.         if (s == null) {  
    7.             s = getSessionFactory().openSession();  
    8.             threadSession.set(s);  
    9.         }  
    10.     } catch (HibernateException ex) {  
    11.         throw new InfrastructureException(ex);  
    12.     }  
    13.     return s;  
    14. }  
    <script type="text/javascript">render_code();</script>
    可以看到在getSession()方法中,首先判断当前线程中有没有放进去session,如果还没有,那么通过sessionFactory ().openSession()来创建一个session,再将session set到线程中,实际是放到当前线程的ThreadLocalMap这个map中,这时,对于这个session的唯一引用就是当前线程中的那个 ThreadLocalMap(下面会讲到),而threadSession作为这个值的key,要取得这个session可以通过 threadSession.get()来得到,里面执行的操作实际是先取得当前线程中的ThreadLocalMap,然后将 threadSession作为key将对应的值取出。这个session相当于线程的私有变量,而不是public的。
    显然,其他线程中是取不到这个session的,他们也只能取到自己的ThreadLocalMap中的东西。要是session是多个线程共享使用的,那还不乱套了。
    试想如果不用ThreadLocal怎么来实现呢?可能就要在action中创建session,然后把session一个个传到service 和dao中,这可够麻烦的。或者可以自己定义一个静态的map,将当前thread作为key,创建的session作为值,put到map中,应该也行,这也是一般人的想法,但事实上,ThreadLocal的实现刚好相反,它是在每个线程中有一个map,而将ThreadLocal实例作为key,这样每个map中的项数很少,而且当线程销毁时相应的东西也一起销毁了,不知道除了这些还有什么其他的好处。

    总之,ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。归纳了两点:
    1。每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。
    2。将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。

    当然如果要把本来线程共享的对象通过ThreadLocal.set()放到线程中也可以,可以实现避免参数传递的访问方式,但是要注意get() 到的是那同一个共享对象,并发访问问题要靠其他手段来解决。但一般来说线程共享的对象通过设置为某类的静态变量就可以实现方便的访问了,似乎没必要放到线程中。

    ThreadLocal的应用场合,我觉得最适合的是按线程多实例(每个线程对应一个实例)的对象的访问,并且这个对象很多地方都要用到。

    下面来看看ThreadLocal的实现原理(jdk1.5源码)

    代码
    1. public class ThreadLocal<T> {  
    2.     /** 
    3.      * ThreadLocals rely on per-thread hash maps attached to each thread 
    4.      * (Thread.threadLocals and inheritableThreadLocals).  The ThreadLocal 
    5.      * objects act as keys, searched via threadLocalHashCode.  This is a 
    6.      * custom hash code (useful only within ThreadLocalMaps) that eliminates 
    7.      * collisions in the common case where consecutively constructed 
    8.      * ThreadLocals are used by the same threads, while remaining well-behaved 
    9.      * in less common cases. 
    10.      */  
    11.     private final int threadLocalHashCode = nextHashCode();  
    12.   
    13.     /** 
    14.      * The next hash code to be given out. Accessed only by like-named method. 
    15.      */  
    16.     private static int nextHashCode = 0;  
    17.   
    18.     /** 
    19.      * The difference between successively generated hash codes - turns 
    20.      * implicit sequential thread-local IDs into near-optimally spread 
    21.      * multiplicative hash values for power-of-two-sized tables. 
    22.      */  
    23.     private static final int HASH_INCREMENT = 0x61c88647;  
    24.   
    25.     /** 
    26.      * Compute the next hash code. The static synchronization used here 
    27.      * should not be a performance bottleneck. When ThreadLocals are 
    28.      * generated in different threads at a fast enough rate to regularly 
    29.      * contend on this lock, memory contention is by far a more serious 
    30.      * problem than lock contention. 
    31.      */  
    32.     private static synchronized int nextHashCode() {  
    33.         int h = nextHashCode;  
    34.         nextHashCode = h + HASH_INCREMENT;  
    35.         return h;  
    36.     }  
    37.   
    38.     /** 
    39.      * Creates a thread local variable. 
    40.      */  
    41.     public ThreadLocal() {  
    42.     }  
    43.   
    44.     /** 
    45.      * Returns the value in the current thread's copy of this thread-local 
    46.      * variable.  Creates and initializes the copy if this is the first time 
    47.      * the thread has called this method. 
    48.      * 
    49.      * @return the current thread's value of this thread-local 
    50.      */  
    51.     public T get() {  
    52.         Thread t = Thread.currentThread();  
    53.         ThreadLocalMap map = getMap(t);  
    54.         if (map != null)  
    55.             return (T)map.get(this);  
    56.   
    57.         // Maps are constructed lazily.  if the map for this thread  
    58.         // doesn't exist, create it, with this ThreadLocal and its  
    59.         // initial value as its only entry.  
    60.         T value = initialValue();  
    61.         createMap(t, value);  
    62.         return value;  
    63.     }  
    64.   
    65.     /** 
    66.      * Sets the current thread's copy of this thread-local variable 
    67.      * to the specified value.  Many applications will have no need for 
    68.      * this functionality, relying solely on the {@link #initialValue} 
    69.      * method to set the values of thread-locals. 
    70.      * 
    71.      * @param value the value to be stored in the current threads' copy of 
    72.      *        this thread-local. 
    73.      */  
    74.     public void set(T value) {  
    75.         Thread t = Thread.currentThread();  
    76.         ThreadLocalMap map = getMap(t);  
    77.         if (map != null)  
    78.             map.set(this, value);  
    79.         else  
    80.             createMap(t, value);  
    81.     }  
    82.   
    83.     /** 
    84.      * Get the map associated with a ThreadLocal. Overridden in 
    85.      * InheritableThreadLocal. 
    86.      * 
    87.      * @param  t the current thread 
    88.      * @return the map 
    89.      */  
    90.     ThreadLocalMap getMap(Thread t) {  
    91.         return t.threadLocals;  
    92.     }  
    93.   
    94.     /** 
    95.      * Create the map associated with a ThreadLocal. Overridden in 
    96.      * InheritableThreadLocal. 
    97.      * 
    98.      * @param t the current thread 
    99.      * @param firstValue value for the initial entry of the map 
    100.      * @param map the map to store. 
    101.      */  
    102.     void createMap(Thread t, T firstValue) {  
    103.         t.threadLocals = new ThreadLocalMap(this, firstValue);  
    104.     }  
    105.   
    106.     .......  
    107.   
    108.     /** 
    109.      * ThreadLocalMap is a customized hash map suitable only for 
    110.      * maintaining thread local values. No operations are exported 
    111.      * outside of the ThreadLocal class. The class is package private to 
    112.      * allow declaration of fields in class Thread.  To help deal with 
    113.      * very large and long-lived usages, the hash table entries use 
    114.      * WeakReferences for keys. However, since reference queues are not 
    115.      * used, stale entries are guaranteed to be removed only when 
    116.      * the table starts running out of space. 
    117.      */  
    118.     static class ThreadLocalMap {  
    119.   
    120.     ........  
    121.   
    122.     }  
    123.   
    124. }  
    <script type="text/javascript">render_code();</script>

    可以看到ThreadLocal类中的变量只有这3个int型:

    代码
    1. private final int threadLocalHashCode = nextHashCode();  
    2. private static int nextHashCode = 0;  
    3. private static final int HASH_INCREMENT = 0x61c88647;  
    <script type="text/javascript">render_code();</script>
    而作为ThreadLocal实例的变量只有 threadLocalHashCode 这一个,nextHashCode 和HASH_INCREMENT 是ThreadLocal类的静态变量,实际上HASH_INCREMENT是一个常量,表示了连续分配的两个ThreadLocal实例的 threadLocalHashCode值的增量,而nextHashCode 的表示了即将分配的下一个ThreadLocal实例的threadLocalHashCode 的值。

    可以来看一下创建一个ThreadLocal实例即new ThreadLocal()时做了哪些操作,从上面看到构造函数ThreadLocal()里什么操作都没有,唯一的操作是这句:

    代码
    1. private final int threadLocalHashCode = nextHashCode();  
    <script type="text/javascript">render_code();</script>
    那么nextHashCode()做了什么呢:
    代码
    1. private static synchronized int nextHashCode() {  
    2.     int h = nextHashCode;  
    3.     nextHashCode = h + HASH_INCREMENT;  
    4.     return h;  
    5. }  
    <script type="text/javascript">render_code();</script> 就是将ThreadLocal类的下一个hashCode值即nextHashCode的值赋给实例的threadLocalHashCode,然后nextHashCode的值增加HASH_INCREMENT这个值。

    因此ThreadLocal实例的变量只有这个threadLocalHashCode,而且是final的,用来区分不同的 ThreadLocal实例,ThreadLocal类主要是作为工具类来使用,那么ThreadLocal.set()进去的对象是放在哪儿的呢?

    看一下上面的set()方法,两句合并一下成为

    代码
    1. ThreadLocalMap map = Thread.currentThread().threadLocals;  
    <script type="text/javascript">render_code();</script>
    这个ThreadLocalMap 类是ThreadLocal中定义的内部类,但是它的实例却用在Thread类中:
    代码
    1. public class Thread implements Runnable {  
    2.     ......  
    3.   
    4.     /* ThreadLocal values pertaining to this thread. This map is maintained 
    5.      * by the ThreadLocal class. */  
    6.     ThreadLocal.ThreadLocalMap threadLocals = null;    
    7.     ......  
    8. }  
    <script type="text/javascript">render_code();</script>

    再看这句:

    代码
    1. if (map != null)  
    2.     map.set(this, value);  
    <script type="text/javascript">render_code();</script>
    也就是将该ThreadLocal实例作为key,要保持的对象作为值,设置到当前线程的ThreadLocalMap 中,get()方法同样大家看了代码也就明白了,ThreadLocalMap 类的代码太多了,我就不帖了,自己去看源码吧。

    写了这么多,也不知讲明白了没有,有什么不当的地方还请大家指出来

     
    展开全文
  • 理解卷积神经网络中的权值共享

    千次阅读 2020-07-04 17:33:36
    简单从共享的角度来说:权重共享即filter的值共享 卷积神经网络两大核心思想: 1.网络局部连接(Local Connectivity) 2.卷积核参数共享(Parameter Sharing) 两者的一个关键作用就是减少参数数量,使运算变得简洁...

    首先介绍单层网络实行的权重共享袁力介绍

    简单从共享的角度来说:权重共享即filter的值共享

    卷积神经网络两大核心思想:

    1.网络局部连接(Local Connectivity)

    2.卷积核参数共享(Parameter Sharing)

    两者的一个关键作用就是减少参数数量,使运算变得简洁、高效,能够在超大规模数据集上运算。

    下面来用最直观的图示,来阐明两者的作用。

    CNN的正确打开方式,如下所示
    在这里插入图片描述
    概括为:一个在这里插入图片描述 的卷积核在图像上扫描,进行特征提取。通常在这里插入图片描述[公式][公式] 的卷积核较为常用,如果channels为 [公式] 的话(32,64是较为常用的通道数),那么参数总量为 在这里插入图片描述

    • 不进行parameter sharing

    如果不用parameter sharing实现上图的运算,卷积核结构就会变成下图所示

    在这里插入图片描述
    这个是不难发现:卷积核的参数数量与图像像素矩阵的大小保持一致,即
    在这里插入图片描述
    例如:Inception V3的输入图像尺寸是192192的,**如果把第一层3332的卷积核去掉参数共享,那么参数数目就会变成192192*32,约为120万个参数,是原来288个参数的50万倍。**

    • 不进行local connectivity
      如果不用局部连接,那当然就是全连接网络了(fully connect),即每个元素单元与隐层的神经原进行全连接,网络结构如下所示。
      在这里插入图片描述

    此时参数量变为 在这里插入图片描述 ,因为像素矩阵很大,所以也会选择较多的隐含层节点,这时一个单隐层的参数数目通常就超过了1千万个,导致网络很难进行训练。


    以下是pytorch对多层网络实行的权重共享代码

    import torch
    import torch.nn as nn
    import random
    import matplotlib.pyplot as plt
     
    # 绘制loss曲线
    def plot_curve(data):
        fig = plt.figure()
        plt.plot(range(len(data)), data, color='blue')
        plt.legend(['value'], loc='upper right')
        plt.xlabel('step')
        plt.ylabel('value')
        plt.show()
     
     
    class DynamicNet(nn.Module):
        def __init__(self, D_in, H, D_out):
            super(DynamicNet, self).__init__()
            self.input_linear = nn.Linear(D_in, H)
            self.middle_linear = nn.Linear(H, H)
            self.output_linear = nn.Linear(H, D_out)
     
        def forward(self, x):
            h_relu = self.input_linear(x).clamp(min=0)
            # 重复利用Middle linear模块
            for _ in range(random.randint(0, 3)):
                h_relu = self.middle_linear(h_relu).clamp(min=0)
            y_pred = self.output_linear(h_relu)
            return y_pred
     
     
    # N是批大小;D是输入维度
    # H是隐藏层维度;D_out是输出维度
    N, D_in, H, D_out = 64, 1000, 100, 10
     
    # 模拟训练数据
    x = torch.randn(N, D_in)
    y = torch.randn(N, D_out)
     
    model = DynamicNet(D_in, H, D_out)
    criterion = nn.MSELoss(reduction='sum')
    # 用平凡的随机梯度下降训练这个奇怪的模型是困难的,所以我们使用了momentum方法。
    optimizer = torch.optim.SGD(model.parameters(), lr=1e-4, momentum=0.9)
     
    loss_list = []
    for t in range(500):
        # 前向传播
        y_pred = model(x)
        # 计算损失
        loss = criterion(y_pred, y)
        loss_list.append(loss.item())
        # 清零梯度,反向传播,更新权重
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
     
    plot_curve(loss_list)
    
    展开全文
  • 一 : 关于Windows的默认共享介绍 网上其实到处都有谈论到,现我也只是整理一下: 在在Windows 系统中,在“我的电脑”上右击“管理”,依次选择“系统工具→共享文件夹→共享”,就会看到一些带有美元“$”标记的...

    一 : 关于Windows的默认共享介绍

    网上其实到处都有谈论到,现我也只是整理一下:

    在在Windows 系统中,在“我的电脑”上右击“管理”,依次选择“系统工具→共享文件夹→共享”,就会看到一些带有美元“$”标记的符号就是Windows系统默认共享,也就是Windows在安装完毕后自动共享的功能。

    当然在cmd命令下输入net share 同样可以查看得到。

    IPC$、ADMIN$、C$、D$都是什么?

    IPC$(Internet Process Connection)可以被理解为一种“专用管道”,可以在连接双方建立一条安全的通道,实现对远程计算机的访问。Windows NT/2000/XP提供了IPC$功能的同时,在初次安装系统时还打开了默认共享,即所有的逻辑共享(C$,D$,E$……)和系统目录(ADMIN$)共享。所有这些共享的目的,都是为了方便管理员的管理,但在有意无意中,导致了系统安全性的隐患。

    默认共享是一项非常有用的功能,只是我们平时用不到罢了。微软的初衷是便于网管进行远程管理。

    默认共享是管理员级别或是有相对应权限的账户的操作。不是别人想查看你共享的东西就能查看到的,主要的限制就是你的管理员密码。同时当共享方式为仅来宾方式时,任何连接的用户权限只能是guest级别的。Windows XP安装后的默认共享方式就是”仅来宾”的方式。
    同时,微软这么说过:“服务器服务需要使用默认 IPC$ 系统管理共享。因此,您不可以删除此共享,我们建议您不要删除由 Windows 为根分区和卷创建的(如 C$)和为系统根文件夹创建的 (ADMIN$) 系统管理共享。删除这些文件夹可能会给依赖这些共享的管理员和程序或服务带来问题。” 只要服务器服务”Server”正在运行当中,就不可能删除IPC$。试图删除只会出现”拒绝访问”的错误提示。当你停止了Server服务后。IPC$会自动消失。

    默认共享不是个漏洞。造成安全隐患的并不是默认共享本身。而是系统使用者本身。

    ///

    当然,针对IPC$ ,额、度娘和谷姐很好,有很多文章-.-  就不转了…

    //

    怎么访问那些共享?

    访问WindowsXP默认共享非常简单:

    一是通过“开始”→“运行”,输入“计算机名或IP地址D$或admin$”(不包括两侧的引号,下同);

    二是使用IE等浏览器,在地址栏中输入上述格式或“file://10.80.34.33/d$”(如图):

    //

    未知的共享开了是不是有些不爽?

    现在来看下怎样关闭这些共享:

    先来看看cmd命令 net share 的使用

     

    C:Documents and SettingsAdministrator>net share ?
    此命令的语法是:

    NET SHARE
    sharename
    sharename=drive:path [/GRANT:user,[READ | CHANGE | FULL]]
    [/USERS:number | /UNLIMITED]
    [/REMARK:"text"]
    [/CACHE:Manual | Documents| Programs | BranchCach
    e | None]
    sharename [/USERS:number | /UNLIMITED]
    [/REMARK:"text"]
    [/CACHE:Manual | Documents | Programs | BranchCache | None]
    {sharename | devicename | drive:path} /DELETE
    sharename computername /DELETE
    参数说明:

    sharename:指共享资源的网络名。如果此名字后面加上“$”字符则此共享就会成为隐含的。
    drive:path:指定将被共享的文件夹的绝对路径(包括驱动器名)。如:C:My Documents。
    /USERS:设置可以同时访问共享资源的最大用户数,“number”指具体的用户数。
    /UNLIMITED:指不限定同时访问共享资源的用户数。
    /REMARK:添加一个有关共享资源的描述性注释,注释内容的文本应该包含在引号(“)中。
    /CACHE:指定访问共享时启动缓存的方法,以便脱机访问此共享。分三种类型:“Manual”指启用脱机客户缓存和手动重新集成,“Automatic”允许启用脱机客户缓存和自动重新集成,“No”不允许使用脱机客户缓存。
    devicename:指一个或多个被共享名所共享的打印机设备(从LPT1:到LPT9:)。
    /DELETE:关闭共享。

    命令:

    net share
    含义:直接显示出本计算机上所有的共享(效果如下图中红色方框所示)

    net share Tmxt
    含义:直接显示出名为Tmxt的共享的详细信息

    (效果如下图中红色方框所示)

    net share admin$ /del
    含义:关闭名admin$的共享。

    ///

    此为一种方法,现还附上其他的关闭默认共享的方法:

    方法二:查找键值:

    禁止C$、D$、E$、ADMIN$一类的共享

    “开始”→“运行”输入“regedit”确定后,打开注册表编辑器,找到“HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceslanmanserverparameters”项,双击右侧窗口中的“AutoShareServer”项将键值由1改为0,这样就能关闭硬盘各分区的共享。如果没有AutoShareServer项,可自己新建一个再改键值。然后还是在这一窗口下再找到“AutoShareWks”项,也把键值由1改为0,关闭admin$共享。最后到“HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsa”项处找到“restrictanonymous”,将键值设为1,关闭IPC$共享。

    注意:本法必须重启机器,但一经改动就会永远停止共享。

    方法三:用批处理:将下面两部分代码保存为两个文件,放在同一目录,运行Name.BAT 即可。

    将下面的代码保存为.BAT文件:

    @ECHO OFF
    TITLE 正在取消默认的分区共享…
    net share admin$ /del
    net share c$ /del
    net share d$ /del
    net share e$ /del
    net share f$ /del

    ……(你有几个硬盘分区就写几行这样的命令)

    保存为NotShare.bat(注意后缀!),然后把这个批处理文件拖到“程序”→“启动”项,这样每次开机就会运行它,也就是通过net命令关闭共享。

    如果哪一天你需要开启某个或某些共享,只要重新编辑这个批处理文件即可(把相应的那个命令行删掉)。

    方法四:将下面的代码保存为 Share.reg 文件:

    Windows Registry Editor Version 5.00

    [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceslanmanserverparameters]
    “AutoShareServer”=dword:00000000
    “AutoShareWks”=dword:00000000
    方法五:停止服务
    控制面板——管理工具——服务——SERVER服务
    (右击)——属性——常规——启动类型——己禁用
    到“计算机管理”窗口中,单击展开左侧的“服务和应用程序”并选中其中的“服务”,此时右侧就列出了所有服务项目。共享服务对应的名称是“Server”(在进程中的名称为services),找到后双击它,在弹出的“常规”标签中把“启动类型”由原来的“自动”更改为“已禁用”。然后单击下面“服务状态”的“停止”按钮,再确认一下就OK了。

    方法六:右键“停止共享”法

    到“计算机管理”窗口中某个共享项(比如H$)上右键单击,选择“停止共享” 并确认后就会关闭这个共享,它下面的共享图标就会消失,重复几次所有的项目都可以停止共享。

    注意:但这种方法治标不治本,如果机器重启的话,这些共享又会恢复。此法比较适合于永不关闭的服务器,简单而且有效。
    方法七:卸载“文件和打印机共享”法

    右击“网上邻居”选“属性”,在弹出的“网络和拨号连接”窗口中右击“本地连接”选“属性”,从“此连接使用下列选定的组件”中选中“Microsoft网络的文件和打印机共享”后,单击下面的“卸载”按钮并确认一下。

    注意:本方法最大的缺陷是当你在某个文件夹上右击时,弹出的快捷菜单中的“共享”一项消失了,因为对应的功能服务已经被卸载掉了!>

    /

    说到底,其实默认共享好像形不成对windows的威胁吧 ,别人如果想进来还得你给他分配权限 ,否则他也进不来。

    ///

    关闭了默认共享,在实际使用中我们也没有出现任何故障,实际上默认共享只在某些情况下用到,关闭默认共享并不会影响上网聊天、收发邮件等普通操作,不过对于域控制器或网络中使用了C/S类型的软件等环境来说,盲目删除默认共享带来的危害是巨大的。下面是从众多故障中选出几个有代表性的分析:

    现象1
    危害指数:★★★★
    危害对象:欲登录域环境的客户机
    出现环境:域环境

    将域控制器上的默认共享全部关闭后,当网络中有客户端计算机想加入这个域时,则会出现问题。现象为Windows 98或Microsoft Windows Millennium Edition的客户端计算机登录到域时会出现“域登录密码不正确”、“没有权限登录域”等提示。一些Windows 2000或Windows XP的计算机登录到网络时也可能出现“域服务器不可用”等信息。如果我们手工将计算机加入域时会出现“域控制器名称没找到”的提示。
    出现上述信息后,我们的客户机根本无法加入建立的域中,只能进行本机登录,在安全性和管理性上都无法达到统一,使企业网络管理无法正常进行,规划好的域无法运行。

    为什么客户端无法正常加入到域中呢?究其原因是客户机在寻找域控制器时是通过广播查找NETLOGON$这个默认共享的,如果此共享被关闭则会出现故障。

    现象2
    危害指数:★★★
    危害对象:网络共享服务
    出现环境:工作组环境、域环境

    在网络中任意一台计算机上禁止所有默认共享后,在网络中其他计算机上使用UNC 路径、映射的驱动器、net use命令、net view命令或通过在“网上邻居”中浏览网络,以远程方式访问或查看关闭默认共享的计算机时会收到“远程服务器不容许访问”、“系统53错误,网络路径不可达”等信息。

    出现上述信息后,网络中的其他计算机就无法访问关闭默认共享的计算机。

    现象3
    危害指数:★★
    危害对象:WINS服务
    出现环境:普通网络、域环境在关闭默认共享的计算机上WINS服务可能无法启动或者WINS控制台显示红色的叉,更有甚者两个故障同时存在。虽然WINS服务在当前网络中应用的范围越来越少,但是通过WINS服务我们还是可以大大加快局域网中主机名的解析速度。WINS服务无法启动或者WINS控制台显示红叉,那么在解析主机名过程中会出现问题。

    WINS服务的异常也是我们将默认共享关闭了所带来的,关闭默认共享会使WINS相关服务与组件的运行出现问题。

    现象4
    危害指数:★★★★★
    危害对象:内网安全体制
    出现环境:普通网络

    网络中使用了瑞星网络版杀毒软件,在使用中将服务器端的默认共享关闭后,客户端出现无法正常连接瑞星杀毒服务器的现象,同时,服务器也无法正常检测客户端的漏洞以及控制客户端升级等操作。

    上述故障自然也是将默认共享关闭造成的,瑞星网络版通过默认共享admin$来管理客户机,当客户机的admin$关闭后服务器将无法通过自身的扫描模块寻找客户机以及它们的漏洞,关闭服务器的admin$后则会出现客户机无法找到网络中的瑞星杀毒服务器的问题。

    值得注意的是,该问题不仅出现在网络版瑞星杀毒软件上,对于大多数网络版杀毒软件来说盲目关闭默认共享都可能带来此危害,甚至某些网络管理软件也会因为admin$的关闭而无法工作。

    /

    那好吧,现在看看怎么开启这些默认共享:

    第一步:检查AutoShareServer和AutoShareWks注册表值,以确保未将它们设置为0。依次点击“开始→运行”,输入regedit,然后按回车键进入注册表编辑器。

    第二步:找到并单击HKEY_LOCAL_
    MACHINESystemCurrentControlSetServic
    esLanmanServerParameters。

    第三步:如果LanmanServerParameter
    s子项中的AutoShareServer 和AutoShareW
    ks DWORD值配置的数值为0,则将该值更改为1(图2)。

    第四步:重新启动计算机。通常运行Windows Server 2003、Windows XP、Windows 2000的计算机会在启动过程中自动创建。

    第五步:启动计算机后,我们可以通过运行CMD进入命令行模式,然后运行net share,在共享列表中应该会查找到Admin$、C$和IPC$等默认共享的存在。

    而通过关闭Server服务、在网卡上去掉Microsoft客户端驱动、以及在网卡上去掉“文件和打印共享”选项等都可关闭默认共享。当使用这些方法关闭默认共享后出现上述问题时,就需要通过开启相应的Server服务,在网卡中添加相应驱动或选项来恢复默认共享。

    //

    一个小东西,-.-整了这么一大串….

    by duke

    二 : win7默认共享文件夹在哪里?win7关闭默认共享文件夹

    有时候我们在使用电脑的时候,不想系统默认共享文件夹,怎么关闭呢,下面小编来分享一下方法,一起来看看吧!

    步骤

    第一步右键桌面上的“计算机”点击“管理

    第二步进去之后,我们在列表中找到“共享文件夹

    第三步点击打开共享文件夹,点击“共享”,我们可以在右方看到系统的共享文件夹

    第四步鼠标右键我们要取消的共享文件夹,选择“停止共享

    第五步我们点击之后,会弹出一个警告对话框,点击“”,如下图所示:

    第六步点击之后,我们可以看到刚刚的共享文件夹已经关闭了,如下图所示:

    以上就是win7关闭默认共享文件夹方法介绍,操作很简单的,大家学会了吗?希望这篇文章能对大家有所帮助!

    三 : win7旗舰版统下如何关闭默认共享文件?win7旗舰版统下关闭默认共享文件的四种方法

     win7旗舰版统下关闭默认共享文件的四种方法 三联

      win7旗舰版统下关闭默认共享文件的四种方法

             方法一:批处理自动关闭法

      1、打开win7系统记事本,在其中输入:net share admin$ /deletenet share c$ /delete;

      2、然后对照“计算机管理工具”中查看的隐藏共享列表,每个一行,然后将文件保存为bat格式,将编辑好的批处理文件拖到开始菜单的启动项中,这样每次开机都会系统就会执行批处理命令,自动将这些默认共享关闭。

      方法二:直接关闭法

      1、双击win7系统桌面上的计算机图标,然后计算机窗口中鼠标右击盘符选择“共享和安全”命令;

            2、在打开的“共享”文件夹选项卡中可以清楚地看到“共享此文件夹”被选中,共享文件名后面有一个“$”标志,这时我们只需选中“不共享此文件夹”选项,然后点击确定按钮,这时会提示你该共享是为管理创建的,但重新启动后共享又会自动被建立;

            3、单击“是”按钮即可关闭。

      方法三:进入计算机管理进行关闭

      1、鼠标右击“计算机”选择“管理”;

            2、在打开的计算机管理左侧选择“共享文件夹”下的“共享”项,这样在右侧则会显示所有隐藏的共享,这时只需要将它们选中并右击,在弹出的菜单中选择“停止共享”命令就可以了。

    进入计算机管理进行关闭

      方法四:通过服务进行关闭

      1、进入win7系统的控制面板,打开“管理工具”中的“服务”;

           2、在右侧的服务列表中找到并双击“Server”服务,单击“停止”按钮,然后将 “启动类型”设为“已禁用”,设置好后单击“确定”按钮即可。

           备注:这个方法会导致正常的共享服务也无法使用了。这对需要使用共享服务的朋友来说就会显的不够便利。

    双击“Server”服务

            以上就是 对win7旗舰版统下关闭默认共享文件的四种方法的就诶是,有此需求的朋友可以动手尝试下。

    四 : win10|win8.1|win7管理共享关闭图文教程

    大家知道win10|win8.1|win7会创建一些隐藏共享文件夹,在文件名称末尾以美元“$”标志区别开。当用户在文件资源管理器的网络节点,或者使用命令查看网络共享时,无法查看到这些隐藏共享,现在就分享win10|win8.1|win7管理共享关闭图文教程,教大家关闭win系统管理共享功能 

           win系统管理共享创建一些隐藏共享文件夹在XP、Vista、Windows7、Windows8/Windows 8.1和Windows10中都存在,目的是让系统管理员、程序以及相关服务能够以此管理网络环境。

      Windows在默认情况下会开启以下隐藏管理共享:

      • 根分区或卷

      • 系统根目录

      • FAX$共享

      • IPC$共享

      • PRINT$共享

      这些共享的开启可以让任何有管理权限进入你的电脑或者活动目录(Active Directory)域(连接状态下)的用户进入任何分区,而并不需要你主动分享文件,因为他已经拿到了你的账户凭据。

            在基于Windows NT架构的系统(XP、Vista、Win7、Win8/Win8.1和Win10等都是)中,所有分区都通过“管理共享”功能对管理员开放共享。

            因此这种机制存在安全隐患,你可以采取以下三种方式彻底关闭该共享功能。

      1、关闭Server服务

      ①在运行、任务管理器或Cortana搜索栏(Win10)/开始菜单搜索栏(Win7)/开始屏幕搜索栏(Win8.1)输入services.msc后回车,打开“服务”

      ②找到Server,双击打开

      ③在“启动类型”中选择“禁用”,然后在“服务状态”点击“停止”后确定

      这种方法能够关闭文章开头提到的管理共享,不过对于需要开启打印和传真等共享和某些文件共享的用户来说,这种方式有些“矫枉过正”。后面两种方式更适合这部分用户。

      2、在注册表中关闭“管理共享”

      虽然是在注册表中操作,但这种方法其实并不费事,不过最好在修改前备份一下注册表,以防修改错误导致不必要的麻烦。可以用软媒魔方的清理大师来完成该操作,方便快捷。

      具体方法如下:

      ①在运行、任务管理器或Cortana搜索栏(Win10)/开始菜单搜索栏(Win7)/开始屏幕搜索栏(Win8.1)输入regedit后回车,打开注册表编辑器

      ②定位到

      HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesLanmanServerParameters

      ③新建DWORD(32位)值,重命名为AutoShareWks,并将其数值数据设置为“0”后点击确定

      3、用软媒魔方的设置大师关闭“管理共享”

      用魔方操作更为简洁,并且不会影响到正常的共享功能,方便高效。

      ①打开最新版软媒魔方,找到“设置大师”

      ②在“网络设置”中选择“网络共享设置”

      ③在“共享设置”中勾选想要取消的管理共享,一般来说前三项都要勾选,记得点击“保存设置”;然后在“共享列表”中可以选择清除IPC共享,该项目风险较高

      至此,三种方法介绍完毕,操作上都没太大难度,对目前主流Windows系统都适用。关键是系统首次安装之后最好就关闭这些“危险因素”,及早预防。

    展开全文
  • 信号量(Semaphore),又被称为信号灯,在多线程环境下用于协调各个线程, 以保证它们能够正确、合理的使用公共资源。信号量维护了一个许可集,我们在初始化Semaphore时需要为这个许可集传入一个数量值,该数量...
  • 好长一段时间没明白共享指针的理解和使用,今天认认真真查了一些资料,搞懂了很多。在这里整理了一下两个链接的内容。 主要参考链接: https://blog.csdn.net/u011866460/article/details/42027457 ...
  • ThreadLocal并不是用来解决共享对象的多线程访问问题。 看了许多有关 ThreadLocal的博客,看完之后会给人一种错觉, ThreadLocal就是用于在多线程情况下防止共享对象的线程安全问题,使用 ThreadLocal之后, ...
  • 【MySQL笔记】正确理解MySQL的事务和隔离级别

    千次阅读 多人点赞 2019-07-05 16:31:09
    正确理解MySQL的事务和隔离级别
  • 深入理解Java并发之synchronized实现原理

    万次阅读 多人点赞 2017-06-04 17:44:44
    【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) ... 出自【zejian的博客】...深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深...
  • 理解什么是线程安全性、原子性

    万次阅读 2019-12-29 11:56:30
    提到多线程这里要说两个概念,就是串行和并行,搞清楚这个我们才能更好的理解多线程。所谓串行其实是相对于单条线程来执行多个任务来说的,我们就拿下载文件来举个例子,我们下载多个文件,在串行中它是按照一定的...
  • 深入理解Java枚举类型(enum)

    万次阅读 多人点赞 2017-05-13 18:27:14
    【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) ... 出自【zejian的博客】 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) ...深入理解
  • 关于CORS跨域问题的理解

    千次阅读 2018-04-13 20:42:14
    跨域资源共享"(Cross-origin resource sharing),但一个请求url的协议,域名,端口三者之间任意与当前页面地址不同即为跨域.它允许阅览器向跨源服务器发送XMLHttpRequest请求,从而客服AJAX只能同源使用的...
  • 正确理解MySQL的乐观锁,悲观锁与MVCC !首先声明,MySQL的测试环境是5.7 前提概念 数据库并发的三种场景 乐观锁和悲观锁的澄清 悲观锁 乐观锁 MVCC多版本并发控制 总结 乐观锁和悲观锁的...
  • delphi中move函数的正确理解

    万次阅读 2009-10-02 14:43:00
    我们能看到以下代码var pSource,pDest:PChar; len: integer;.......................//一些代码Move(pSource,pDest,len);... //正确看起来确实好像是传值,而不是传地址,但是各位别忘了,这不是C,C++,而是Delph
  • 正确理解SOA、SaaS和云计算的关系

    千次阅读 2010-09-07 17:29:00
    随着云计算的概念受到越来越多的人的推崇和论证,“云上的日子”看起来离我们越来越近了。...我们应当如何正确理解这三者之间的关系呢?解惑云计算、SOA与SaaS云计算涵盖的范围很广泛,内容也很丰富。
  • 今天我们来聊聊Android L(5.0)引入的新特性:页面内容过渡动画和页面共享动画,这两个特性都是基于我们前面已经说过的Transition动画,如果你对Transition动画不太属性,请先看我前面的两篇文章。在5.0之前,我们从...
  • 关于关键字volatile可以说是Java虚拟机提供的轻量级的同步机制,但是它并不容易完全被正常、完整地理解,以至于许多程序员都不习惯去使用它,遇到需要处理多线程数据竞争问题的时候一律使用Synchronized来进行同步。...
  • 条款11:理解自定义分配器的正确用法你用了基准测试,性能剖析,而且实验了你的方法得到默认的STL内存管理器(即allocator )在你的STL需求中太慢、浪费内存或造成过度的碎片的结论,并且你肯定你自己能做得比它好。...
  • 关于CUDA中__threadfence的理解

    万次阅读 2013-01-15 21:20:04
    __threadfence函数是memory fence函数,用来保证线程间数据通信的可靠性。...(1)__threadfence:一个线程调用__threadfence后,该线程在该语句前对全局存储器或共享存储器的访问已经全部完成,执行结果对
  • (多选题)关于volatile关键字,下列描述不正确的是? A.用volatile修饰的变量,每次更新对其他线程都是立即可见的。 B.对volatile变量的操作是原子性的。 C.对volatile变量的操作不会造成阻塞。 D.不依赖其他锁...
  • springboot 配置shiro多项目之间共享session   
  • 写在前面 写【高并发专题】有一段时间了,一些读者...其实,造成这种现象的本质原因就是没有透彻的理解并发编程的精髓,而学好并发编程的关键是需要弄懂三个核心问题:分工、同步和互斥。 分工 比较官方的解释为...
  • 1、用VirtualBox虚拟机的共享文件夹设置共享的本地文件(我的是设置的是本地E盘,java文件夹) 2、进入虚拟机Ubuntu系统,打开终端,用root用户操作(sudo -s回车输入密码) 首先在虚拟机上创建一个共享目录 eg:...
  • 关于GPL协议的理解(开源与商用、免费与收费的理解
  • 关于数据库中一些定义名词的理解

    千次阅读 2020-02-24 16:43:31
    数据库:长期存储在计算机内、有组织的、可共享的大量数据的集合。 数据库管理系统:位于用户和操作系统之间的一层数据管理软件。 数据库系统:是由数据库及其管理软件组成的系统。 个人理解:数据库指的是一些数据...
  • 【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) ... 出自【zejian的博客】 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) ...深入理解
  • 了解并发编程中对象的共享

    万次阅读 2019-12-30 11:59:56
    我们可以进一步理解为什么在访问某个共享且可变的变量时,要求所有线程在同一个锁上同步,就是为了确保某个线程写入该变量的值对于其他线程来说都是可见的,否则,如果一个线程在未持有正确锁的情况下读取某个变量,...
  • 如何从RNN起步,一步一步通俗理解LSTM

    万次阅读 多人点赞 2019-05-06 23:47:54
    提到LSTM,之前学过的同学可能最先想到的是ChristopherOlah的博文《理解LSTM网络》,这篇文章确实厉害,网上流传也相当之广,而且当你看过了网上很多关于LSTM的文章之后,你会发现这篇文章确实经典。不过呢,如果你...
  • “不要通过共享内存来通信,要通过通信来共享内存”,这句话是GO社区中非常经典的一句话,但是我们如何理解这句话呢? GO语言的协程(goroutine)是从进程、线程基础上发展而来的,它比进程线程更轻量级,但是都是...
  • 深入理解进程和线程

    千次阅读 2015-10-30 23:40:52
    在之前的博客里面(进程通信),我简单的区分了一下...线程是CPU运行调度的基本单位,线程必须被包含在进程中,一个进程可以有很多线程(至少有一个),这些线程有自己的资源(如栈,寄存器)也共享进程的许多资源。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 236,387
精华内容 94,554
关键字:

关于共享的理解正确的是