     /// Try to aquire a lock. This method will block until lock the already aquired by other process.
     ///
     /// Note: This method can throw if underlying POSIX methods fail.
-    public func lock() throws {
+    public func lock(type: LockType = .exclusive) throws {
       #if os(Windows)
         if handle == nil {
             let h = lockFile.pathString.withCString(encodedAs: UTF16.self, {
-                CreateFileW(
-                    $0,
-                    UInt32(GENERIC_READ) | UInt32(GENERIC_WRITE),
-                    0,
-                    nil,
-                    DWORD(OPEN_ALWAYS),
-                    DWORD(FILE_ATTRIBUTE_NORMAL),
-                    nil
-                )
+                switch mode {
+                case .exclusive:
+                    CreateFileW(
+                        $0,
+                        UInt32(GENERIC_READ) | UInt32(GENERIC_WRITE),
+                        0,
+                        nil,
+                        DWORD(OPEN_ALWAYS),
+                        DWORD(FILE_ATTRIBUTE_NORMAL),
+                        nil
+                    )
+                case .shared:
+                    CreateFileW(
+                        $0,
+                        UInt32(GENERIC_READ) | UInt32(GENERIC_WRITE),
+                        DWORD(FILE_SHARE_READ),
+                        nil,
+                        DWORD(OPEN_ALWAYS),
+                        DWORD(FILE_ATTRIBUTE_NORMAL),
+                        nil
+                    )
+                }
             })
             if h == INVALID_HANDLE_VALUE {
                 throw FileSystemError(errno: Int32(GetLastError()))

    }

    /// Execute the given block while holding the lock.
    public func withLock<T>(_ body: () throws -> T) throws -> T {
        try lock()
        defer { unlock() }
        return try body()
    }

        overlapped.Offset = 0
        overlapped.OffsetHigh = 0
        overlapped.hEvent = nil
        switch mode {
        case .exclusive:
            if !LockFileEx(handle, DWORD(LOCKFILE_EXCLUSIVE_LOCK), 0,
                           DWORD(INT_MAX), DWORD(INT_MAX), &overlapped) {
                throw ProcessLockError.unableToAquireLock(errno: Int32(GetLastError()))
            }
        case .shared:
            if !LockFileEx(handle, 0, 0,
                           DWORD(INT_MAX), DWORD(INT_MAX), &overlapped) {
                throw ProcessLockError.unableToAquireLock(errno: Int32(GetLastError()))
            }
        }
      #else
        // Open the lock file.
