I got a solution here in the link below
https://sitecorejunkie.com/2013/09/28/periodically-unlock-items-of-idle-users-in-sitecore/
We can create a task and run after every predefined no of hours. e.g 4 hrs in below example
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<settings>
<setting name="UnlockItems.ElapsedTimeWhenIdle" value="00:04:00:00" />
</settings>
Code for UnlockItems class
using System;
using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Security.Accounts;
using Sitecore.Tasks;
using Sitecore.Web.Authentication;
namespace Sitecore.Sandbox.Tasks
{
public class UnlockItems
{
private static readonly TimeSpan ElapsedTimeWhenIdle = GetElapsedTimeWhenIdle();
public void UnlockIdleUserItems(Item[] items, CommandItem command, ScheduleItem schedule)
{
if (ElapsedTimeWhenIdle == TimeSpan.Zero)
{
return;
}
IEnumerable<Item> lockedItems = GetLockedItems(schedule.Database);
foreach (Item lockedItem in lockedItems)
{
UnlockIfApplicable(lockedItem);
}
}
private static IEnumerable<Item> GetLockedItems(Database database)
{
Assert.ArgumentNotNull(database, "database");
return database.SelectItems("fast://*[@__lock='%owner=%']");
}
private void UnlockIfApplicable(Item item)
{
Assert.ArgumentNotNull(item, "item");
if (!ShouldUnlockItem(item))
{
return;
}
Unlock(item);
}
private static bool ShouldUnlockItem(Item item)
{
Assert.ArgumentNotNull(item, "item");
if(!item.Locking.IsLocked())
{
return false;
}
string owner = item.Locking.GetOwner();
return !IsUserAdmin(owner) && IsUserIdle(owner);
}
private static bool IsUserAdmin(string username)
{
Assert.ArgumentNotNullOrEmpty(username, "username");
User user = User.FromName(username, false);
Assert.IsNotNull(user, "User must be null due to a wrinkle in the interwebs :-/");
return user.IsAdministrator;
}
private static bool IsUserIdle(string username)
{
Assert.ArgumentNotNullOrEmpty(username, "username");
DomainAccessGuard.Session userSession = DomainAccessGuard.Sessions.Find(session => session.UserName == username);
if(userSession == null)
{
return true;
}
return userSession.LastRequest.Add(ElapsedTimeWhenIdle) <= DateTime.Now;
}
private void Unlock(Item item)
{
Assert.ArgumentNotNull(item, "item");
try
{
string owner = item.Locking.GetOwner();
item.Editing.BeginEdit();
item.Locking.Unlock();
item.Editing.EndEdit();
Log.Info(string.Format("Unlocked {0} - was locked by {1}", item.Paths.Path, owner), this);
}
catch (Exception ex)
{
Log.Error(this.ToString(), ex, this);
}
}
private static TimeSpan GetElapsedTimeWhenIdle()
{
TimeSpan elapsedTimeWhenIdle;
if (TimeSpan.TryParse(Settings.GetSetting("UnlockItems.ElapsedTimeWhenIdle"), out elapsedTimeWhenIdle))
{
return elapsedTimeWhenIdle;
}
return TimeSpan.Zero;
}
}
}